SparseArray.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Util/StdTypes.h>
  7. #include <AnKi/Util/Assert.h>
  8. #include <AnKi/Util/Array.h>
  9. #include <utility>
  10. namespace anki {
  11. /// @addtogroup util_containers
  12. /// @{
  13. /// Sparse array iterator.
  14. template<typename TValuePointer, typename TValueReference, typename TSparseArrayPtr>
  15. class SparseArrayIterator
  16. {
  17. template<typename, typename, typename>
  18. friend class SparseArray;
  19. public:
  20. using Index = typename RemovePointer<TSparseArrayPtr>::Type::Index;
  21. /// Default constructor.
  22. SparseArrayIterator()
  23. : m_array(nullptr)
  24. , m_elementIdx(getMaxNumericLimit<Index>())
  25. #if ANKI_EXTRA_CHECKS
  26. , m_iteratorVer(kMaxU32)
  27. #endif
  28. {
  29. }
  30. /// Copy.
  31. SparseArrayIterator(const SparseArrayIterator& b)
  32. : m_array(b.m_array)
  33. , m_elementIdx(b.m_elementIdx)
  34. #if ANKI_EXTRA_CHECKS
  35. , m_iteratorVer(b.m_iteratorVer)
  36. #endif
  37. {
  38. }
  39. /// Allow conversion from iterator to const iterator.
  40. template<typename YValuePointer, typename YValueReference, typename YSparseArrayPtr>
  41. SparseArrayIterator(const SparseArrayIterator<YValuePointer, YValueReference, YSparseArrayPtr>& b)
  42. : m_array(b.m_array)
  43. , m_elementIdx(b.m_elementIdx)
  44. #if ANKI_EXTRA_CHECKS
  45. , m_iteratorVer(b.m_iteratorVer)
  46. #endif
  47. {
  48. }
  49. SparseArrayIterator(TSparseArrayPtr arr, Index modIdx
  50. #if ANKI_EXTRA_CHECKS
  51. ,
  52. U32 ver
  53. #endif
  54. )
  55. : m_array(arr)
  56. , m_elementIdx(modIdx)
  57. #if ANKI_EXTRA_CHECKS
  58. , m_iteratorVer(ver)
  59. #endif
  60. {
  61. ANKI_ASSERT(arr);
  62. }
  63. SparseArrayIterator& operator=(const SparseArrayIterator& b)
  64. {
  65. m_array = b.m_array;
  66. m_elementIdx = b.m_elementIdx;
  67. #if ANKI_EXTRA_CHECKS
  68. m_iteratorVer = b.m_iteratorVer;
  69. #endif
  70. return *this;
  71. }
  72. TValueReference operator*() const
  73. {
  74. check();
  75. return m_array->m_elements[m_elementIdx];
  76. }
  77. TValuePointer operator->() const
  78. {
  79. check();
  80. return &m_array->m_elements[m_elementIdx];
  81. }
  82. SparseArrayIterator& operator++()
  83. {
  84. check();
  85. m_elementIdx = m_array->iterate(m_elementIdx, 1);
  86. return *this;
  87. }
  88. SparseArrayIterator operator++(int)
  89. {
  90. check();
  91. SparseArrayIterator out = *this;
  92. ++(*this);
  93. return out;
  94. }
  95. SparseArrayIterator operator+(Index n) const
  96. {
  97. check();
  98. Index pos = m_array->iterate(m_elementIdx, n);
  99. return SparseArrayIterator(m_array, pos);
  100. }
  101. SparseArrayIterator& operator+=(Index n)
  102. {
  103. check();
  104. m_elementIdx = m_array->iterate(m_elementIdx, n);
  105. return *this;
  106. }
  107. Bool operator==(const SparseArrayIterator& b) const
  108. {
  109. ANKI_ASSERT(m_array == b.m_array);
  110. ANKI_ASSERT(m_iteratorVer == b.m_iteratorVer);
  111. return m_elementIdx == b.m_elementIdx;
  112. }
  113. Bool operator!=(const SparseArrayIterator& b) const
  114. {
  115. return !(*this == b);
  116. }
  117. Index getKey() const
  118. {
  119. check();
  120. return m_elementIdx;
  121. }
  122. private:
  123. TSparseArrayPtr m_array;
  124. Index m_elementIdx;
  125. #if ANKI_EXTRA_CHECKS
  126. U32 m_iteratorVer; ///< See SparseArray::m_iteratorVer.
  127. #endif
  128. void check() const
  129. {
  130. ANKI_ASSERT(m_array);
  131. ANKI_ASSERT(m_elementIdx != getMaxNumericLimit<Index>());
  132. ANKI_ASSERT(m_array->m_metadata[m_elementIdx].m_alive);
  133. ANKI_ASSERT(m_array->m_iteratorVer == m_iteratorVer);
  134. }
  135. };
  136. /// Contains the default configuration for SparseArray.
  137. /// @memberof SparseArray
  138. class SparseArrayDefaultConfig
  139. {
  140. public:
  141. /// Indicates the max size of the sparse indices it can accept. Can be U32 or U64.
  142. using Index = U32;
  143. /// The initial storage size of the array.
  144. static constexpr Index getInitialStorageSize()
  145. {
  146. return 64;
  147. }
  148. /// The number of linear probes.
  149. static constexpr U32 getLinearProbingCount()
  150. {
  151. return 8;
  152. }
  153. /// Load factor. If storage is loaded more than getMaxLoadFactor() then increase it.
  154. static constexpr F32 getMaxLoadFactor()
  155. {
  156. return 0.8f;
  157. }
  158. };
  159. /// Sparse array.
  160. /// @tparam T The type of the valut it will hold.
  161. /// @tparam TConfig A class that has configuration required by the SparseArray. See SparseArrayDefaultConfig for
  162. /// details.
  163. template<typename T, typename TMemoryPool = SingletonMemoryPoolWrapper<DefaultMemoryPool>, typename TConfig = SparseArrayDefaultConfig>
  164. class SparseArray
  165. {
  166. template<typename, typename, typename>
  167. friend class SparseArrayIterator;
  168. public:
  169. // Typedefs
  170. using Config = TConfig;
  171. using Value = T;
  172. using Iterator = SparseArrayIterator<T*, T&, SparseArray*>;
  173. using ConstIterator = SparseArrayIterator<const T*, const T&, const SparseArray*>;
  174. using Index = typename Config::Index;
  175. SparseArray(const TMemoryPool& pool = TMemoryPool())
  176. : m_pool(pool)
  177. {
  178. }
  179. SparseArray(const Config& config, const TMemoryPool& pool = TMemoryPool())
  180. : m_pool(pool)
  181. , m_config(config)
  182. {
  183. }
  184. /// Copy.
  185. SparseArray(const SparseArray& b)
  186. {
  187. *this = b;
  188. }
  189. /// Move.
  190. SparseArray(SparseArray&& b)
  191. {
  192. *this = std::move(b);
  193. }
  194. /// Destroy.
  195. ~SparseArray()
  196. {
  197. destroy();
  198. }
  199. /// Copy.
  200. SparseArray& operator=(const SparseArray& b);
  201. /// Move operator.
  202. SparseArray& operator=(SparseArray&& b)
  203. {
  204. destroy();
  205. m_elements = b.m_elements;
  206. m_metadata = b.m_metadata;
  207. m_elementCount = b.m_elementCount;
  208. m_capacity = b.m_capacity;
  209. m_config = std::move(b.m_config);
  210. invalidateIterators();
  211. b.resetMembers();
  212. return *this;
  213. }
  214. /// Get begin.
  215. Iterator getBegin()
  216. {
  217. return Iterator(this, findFirstAlive()
  218. #if ANKI_EXTRA_CHECKS
  219. ,
  220. m_iteratorVer
  221. #endif
  222. );
  223. }
  224. /// Get begin.
  225. ConstIterator getBegin() const
  226. {
  227. return ConstIterator(this, findFirstAlive()
  228. #if ANKI_EXTRA_CHECKS
  229. ,
  230. m_iteratorVer
  231. #endif
  232. );
  233. }
  234. /// Get end.
  235. Iterator getEnd()
  236. {
  237. return Iterator(this, getMaxNumericLimit<Index>()
  238. #if ANKI_EXTRA_CHECKS
  239. ,
  240. m_iteratorVer
  241. #endif
  242. );
  243. }
  244. /// Get end.
  245. ConstIterator getEnd() const
  246. {
  247. return ConstIterator(this, getMaxNumericLimit<Index>()
  248. #if ANKI_EXTRA_CHECKS
  249. ,
  250. m_iteratorVer
  251. #endif
  252. );
  253. }
  254. /// Get begin.
  255. Iterator begin()
  256. {
  257. return getBegin();
  258. }
  259. /// Get begin.
  260. ConstIterator begin() const
  261. {
  262. return getBegin();
  263. }
  264. /// Get end.
  265. Iterator end()
  266. {
  267. return getEnd();
  268. }
  269. /// Get end.
  270. ConstIterator end() const
  271. {
  272. return getEnd();
  273. }
  274. /// Get the number of elements in the array.
  275. PtrSize getSize() const
  276. {
  277. return m_elementCount;
  278. }
  279. /// Return true if it's empty and false otherwise.
  280. Bool isEmpty() const
  281. {
  282. return m_elementCount == 0;
  283. }
  284. /// Destroy the array and free its elements.
  285. void destroy();
  286. /// Set a value to an index.
  287. template<typename... TArgs>
  288. Iterator emplace(Index idx, TArgs&&... args);
  289. /// Get an iterator.
  290. Iterator find(Index idx)
  291. {
  292. return Iterator(this, findInternal(idx)
  293. #if ANKI_EXTRA_CHECKS
  294. ,
  295. m_iteratorVer
  296. #endif
  297. );
  298. }
  299. /// Get an iterator.
  300. ConstIterator find(Index idx) const
  301. {
  302. return ConstIterator(this, findInternal(idx)
  303. #if ANKI_EXTRA_CHECKS
  304. ,
  305. m_iteratorVer
  306. #endif
  307. );
  308. }
  309. /// Remove an element.
  310. void erase(Iterator it);
  311. /// Check the validity of the array.
  312. void validate() const;
  313. const Config& getConfig() const
  314. {
  315. return m_config;
  316. }
  317. protected:
  318. /// Element metadata.
  319. class Metadata
  320. {
  321. public:
  322. Index m_idx;
  323. Bool m_alive;
  324. };
  325. TMemoryPool m_pool;
  326. Value* m_elements = nullptr;
  327. Metadata* m_metadata = nullptr;
  328. Index m_elementCount = 0;
  329. Index m_capacity = 0;
  330. Config m_config;
  331. #if ANKI_EXTRA_CHECKS
  332. /// Iterators version. Used to check if iterators point to the newest storage. Needs to be changed whenever we need
  333. /// to invalidate iterators.
  334. U32 m_iteratorVer = 0;
  335. #endif
  336. /// Wrap an index.
  337. Index mod(const Index idx) const
  338. {
  339. ANKI_ASSERT(m_capacity > 0);
  340. ANKI_ASSERT(isPowerOfTwo(m_capacity));
  341. return idx & (m_capacity - 1);
  342. }
  343. /// Wrap an index.
  344. static Index mod(const Index idx, Index capacity)
  345. {
  346. ANKI_ASSERT(capacity > 0);
  347. ANKI_ASSERT(isPowerOfTwo(capacity));
  348. return idx & (capacity - 1);
  349. }
  350. F32 calcLoadFactor() const
  351. {
  352. ANKI_ASSERT(m_elementCount <= m_capacity);
  353. ANKI_ASSERT(m_capacity > 0);
  354. return F32(m_elementCount) / F32(m_capacity);
  355. }
  356. /// Insert a value. This method will move the val to a new place.
  357. /// @return One if the idx was a new element or zero if the idx was there already.
  358. Index insert(Index idx, Value& val);
  359. /// Grow the storage and re-insert.
  360. void grow();
  361. /// Compute the distance between a desired position and the current one. This method does a trick with capacity to
  362. /// account for wrapped positions.
  363. Index distanceFromDesired(const Index crntPos, const Index desiredPos) const
  364. {
  365. return mod(crntPos + m_capacity - desiredPos);
  366. }
  367. /// Find the first alive element.
  368. Index findFirstAlive() const
  369. {
  370. if(m_elementCount == 0)
  371. {
  372. return getMaxNumericLimit<Index>();
  373. }
  374. for(Index i = 0; i < m_capacity; ++i)
  375. {
  376. if(m_metadata[i].m_alive)
  377. {
  378. return i;
  379. }
  380. }
  381. ANKI_ASSERT(0);
  382. return getMaxNumericLimit<Index>();
  383. }
  384. /// Find an element and return its position inside m_elements.
  385. Index findInternal(Index idx) const;
  386. /// Reset the class.
  387. void resetMembers()
  388. {
  389. m_elements = nullptr;
  390. m_metadata = nullptr;
  391. m_elementCount = 0;
  392. m_capacity = 0;
  393. invalidateIterators();
  394. }
  395. /// Iterate a number of elements.
  396. Index iterate(Index pos, Index n) const
  397. {
  398. ANKI_ASSERT(pos < m_capacity);
  399. ANKI_ASSERT(n > 0);
  400. ANKI_ASSERT(m_metadata[pos].m_alive);
  401. while(n > 0 && ++pos < m_capacity)
  402. {
  403. ANKI_ASSERT(m_metadata[pos].m_alive == 1 || m_metadata[pos].m_alive == 0);
  404. n -= Index(m_metadata[pos].m_alive);
  405. }
  406. return (pos >= m_capacity) ? getMaxNumericLimit<Index>() : pos;
  407. }
  408. template<typename... TArgs>
  409. void emplaceInternal(Index idx, TArgs&&... args);
  410. void destroyElement(Value& v)
  411. {
  412. v.~Value();
  413. #if ANKI_EXTRA_CHECKS
  414. memset(&v, 0xC, sizeof(v));
  415. #endif
  416. }
  417. void invalidateIterators()
  418. {
  419. #if ANKI_EXTRA_CHECKS
  420. ++m_iteratorVer;
  421. #endif
  422. }
  423. F32 getMaxLoadFactor() const
  424. {
  425. const F32 f = m_config.getMaxLoadFactor();
  426. ANKI_ASSERT(f > 0.0f && f < 1.0f);
  427. return f;
  428. }
  429. U32 getLinearProbingCount() const
  430. {
  431. const U32 o = m_config.getLinearProbingCount();
  432. ANKI_ASSERT(o > 0);
  433. return o;
  434. }
  435. Index getInitialStorageSize() const
  436. {
  437. const Index o = m_config.getInitialStorageSize();
  438. ANKI_ASSERT(o > 0);
  439. return o;
  440. }
  441. };
  442. /// @}
  443. } // end namespace anki
  444. #include <AnKi/Util/SparseArray.inl.h>