sparse_array.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. // Copyright 2006 The RE2 Authors. All Rights Reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. #ifndef UTIL_SPARSE_ARRAY_H_
  5. #define UTIL_SPARSE_ARRAY_H_
  6. // DESCRIPTION
  7. //
  8. // SparseArray<T>(m) is a map from integers in [0, m) to T values.
  9. // It requires (sizeof(T)+sizeof(int))*m memory, but it provides
  10. // fast iteration through the elements in the array and fast clearing
  11. // of the array. The array has a concept of certain elements being
  12. // uninitialized (having no value).
  13. //
  14. // Insertion and deletion are constant time operations.
  15. //
  16. // Allocating the array is a constant time operation
  17. // when memory allocation is a constant time operation.
  18. //
  19. // Clearing the array is a constant time operation (unusual!).
  20. //
  21. // Iterating through the array is an O(n) operation, where n
  22. // is the number of items in the array (not O(m)).
  23. //
  24. // The array iterator visits entries in the order they were first
  25. // inserted into the array. It is safe to add items to the array while
  26. // using an iterator: the iterator will visit indices added to the array
  27. // during the iteration, but will not re-visit indices whose values
  28. // change after visiting. Thus SparseArray can be a convenient
  29. // implementation of a work queue.
  30. //
  31. // The SparseArray implementation is NOT thread-safe. It is up to the
  32. // caller to make sure only one thread is accessing the array. (Typically
  33. // these arrays are temporary values and used in situations where speed is
  34. // important.)
  35. //
  36. // The SparseArray interface does not present all the usual STL bells and
  37. // whistles.
  38. //
  39. // Implemented with reference to Briggs & Torczon, An Efficient
  40. // Representation for Sparse Sets, ACM Letters on Programming Languages
  41. // and Systems, Volume 2, Issue 1-4 (March-Dec. 1993), pp. 59-69.
  42. //
  43. // Briggs & Torczon popularized this technique, but it had been known
  44. // long before their paper. They point out that Aho, Hopcroft, and
  45. // Ullman's 1974 Design and Analysis of Computer Algorithms and Bentley's
  46. // 1986 Programming Pearls both hint at the technique in exercises to the
  47. // reader (in Aho & Hopcroft, exercise 2.12; in Bentley, column 1
  48. // exercise 8).
  49. //
  50. // Briggs & Torczon describe a sparse set implementation. I have
  51. // trivially generalized it to create a sparse array (actually the original
  52. // target of the AHU and Bentley exercises).
  53. // IMPLEMENTATION
  54. //
  55. // SparseArray is an array dense_ and an array sparse_ of identical size.
  56. // At any point, the number of elements in the sparse array is size_.
  57. //
  58. // The array dense_ contains the size_ elements in the sparse array (with
  59. // their indices),
  60. // in the order that the elements were first inserted. This array is dense:
  61. // the size_ pairs are dense_[0] through dense_[size_-1].
  62. //
  63. // The array sparse_ maps from indices in [0,m) to indices in [0,size_).
  64. // For indices present in the array, dense_[sparse_[i]].index_ == i.
  65. // For indices not present in the array, sparse_ can contain any value at all,
  66. // perhaps outside the range [0, size_) but perhaps not.
  67. //
  68. // The lax requirement on sparse_ values makes clearing the array very easy:
  69. // set size_ to 0. Lookups are slightly more complicated.
  70. // An index i has a value in the array if and only if:
  71. // sparse_[i] is in [0, size_) AND
  72. // dense_[sparse_[i]].index_ == i.
  73. // If both these properties hold, only then it is safe to refer to
  74. // dense_[sparse_[i]].value_
  75. // as the value associated with index i.
  76. //
  77. // To insert a new entry, set sparse_[i] to size_,
  78. // initialize dense_[size_], and then increment size_.
  79. //
  80. // To make the sparse array as efficient as possible for non-primitive types,
  81. // elements may or may not be destroyed when they are deleted from the sparse
  82. // array through a call to resize(). They immediately become inaccessible, but
  83. // they are only guaranteed to be destroyed when the SparseArray destructor is
  84. // called.
  85. //
  86. // A moved-from SparseArray will be empty.
  87. // Doing this simplifies the logic below.
  88. #ifndef __has_feature
  89. #define __has_feature(x) 0
  90. #endif
  91. #include <assert.h>
  92. #include <stdint.h>
  93. #if __has_feature(memory_sanitizer)
  94. #include <sanitizer/msan_interface.h>
  95. #endif
  96. #include <algorithm>
  97. #include <memory>
  98. #include <utility>
  99. #include "util/pod_array.h"
  100. namespace re2 {
  101. template<typename Value>
  102. class SparseArray {
  103. public:
  104. SparseArray();
  105. explicit SparseArray(int max_size);
  106. ~SparseArray();
  107. // IndexValue pairs: exposed in SparseArray::iterator.
  108. class IndexValue;
  109. typedef IndexValue* iterator;
  110. typedef const IndexValue* const_iterator;
  111. SparseArray(const SparseArray& src);
  112. SparseArray(SparseArray&& src);
  113. SparseArray& operator=(const SparseArray& src);
  114. SparseArray& operator=(SparseArray&& src);
  115. // Return the number of entries in the array.
  116. int size() const {
  117. return size_;
  118. }
  119. // Indicate whether the array is empty.
  120. int empty() const {
  121. return size_ == 0;
  122. }
  123. // Iterate over the array.
  124. iterator begin() {
  125. return dense_.data();
  126. }
  127. iterator end() {
  128. return dense_.data() + size_;
  129. }
  130. const_iterator begin() const {
  131. return dense_.data();
  132. }
  133. const_iterator end() const {
  134. return dense_.data() + size_;
  135. }
  136. // Change the maximum size of the array.
  137. // Invalidates all iterators.
  138. void resize(int new_max_size);
  139. // Return the maximum size of the array.
  140. // Indices can be in the range [0, max_size).
  141. int max_size() const {
  142. if (dense_.data() != NULL)
  143. return dense_.size();
  144. else
  145. return 0;
  146. }
  147. // Clear the array.
  148. void clear() {
  149. size_ = 0;
  150. }
  151. // Check whether index i is in the array.
  152. bool has_index(int i) const;
  153. // Comparison function for sorting.
  154. // Can sort the sparse array so that future iterations
  155. // will visit indices in increasing order using
  156. // std::sort(arr.begin(), arr.end(), arr.less);
  157. static bool less(const IndexValue& a, const IndexValue& b);
  158. public:
  159. // Set the value at index i to v.
  160. iterator set(int i, const Value& v) {
  161. return SetInternal(true, i, v);
  162. }
  163. // Set the value at new index i to v.
  164. // Fast but unsafe: only use if has_index(i) is false.
  165. iterator set_new(int i, const Value& v) {
  166. return SetInternal(false, i, v);
  167. }
  168. // Set the value at index i to v.
  169. // Fast but unsafe: only use if has_index(i) is true.
  170. iterator set_existing(int i, const Value& v) {
  171. return SetExistingInternal(i, v);
  172. }
  173. // Get the value at index i.
  174. // Fast but unsafe: only use if has_index(i) is true.
  175. Value& get_existing(int i) {
  176. assert(has_index(i));
  177. return dense_[sparse_[i]].value_;
  178. }
  179. const Value& get_existing(int i) const {
  180. assert(has_index(i));
  181. return dense_[sparse_[i]].value_;
  182. }
  183. private:
  184. iterator SetInternal(bool allow_existing, int i, const Value& v) {
  185. DebugCheckInvariants();
  186. if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(max_size())) {
  187. assert(false && "illegal index");
  188. // Semantically, end() would be better here, but we already know
  189. // the user did something stupid, so begin() insulates them from
  190. // dereferencing an invalid pointer.
  191. return begin();
  192. }
  193. if (!allow_existing) {
  194. assert(!has_index(i));
  195. create_index(i);
  196. } else {
  197. if (!has_index(i))
  198. create_index(i);
  199. }
  200. return SetExistingInternal(i, v);
  201. }
  202. iterator SetExistingInternal(int i, const Value& v) {
  203. DebugCheckInvariants();
  204. assert(has_index(i));
  205. dense_[sparse_[i]].value_ = v;
  206. DebugCheckInvariants();
  207. return dense_.data() + sparse_[i];
  208. }
  209. // Add the index i to the array.
  210. // Only use if has_index(i) is known to be false.
  211. // Since it doesn't set the value associated with i,
  212. // this function is private, only intended as a helper
  213. // for other methods.
  214. void create_index(int i);
  215. // In debug mode, verify that some invariant properties of the class
  216. // are being maintained. This is called at the end of the constructor
  217. // and at the beginning and end of all public non-const member functions.
  218. void DebugCheckInvariants() const;
  219. // Initializes memory for elements [min, max).
  220. void MaybeInitializeMemory(int min, int max) {
  221. #if __has_feature(memory_sanitizer)
  222. __msan_unpoison(sparse_.data() + min, (max - min) * sizeof sparse_[0]);
  223. #elif defined(RE2_ON_VALGRIND)
  224. for (int i = min; i < max; i++) {
  225. sparse_[i] = 0xababababU;
  226. }
  227. #endif
  228. }
  229. int size_ = 0;
  230. PODArray<int> sparse_;
  231. PODArray<IndexValue> dense_;
  232. };
  233. template<typename Value>
  234. SparseArray<Value>::SparseArray() = default;
  235. template<typename Value>
  236. SparseArray<Value>::SparseArray(const SparseArray& src)
  237. : size_(src.size_),
  238. sparse_(src.max_size()),
  239. dense_(src.max_size()) {
  240. std::copy_n(src.sparse_.data(), src.max_size(), sparse_.data());
  241. std::copy_n(src.dense_.data(), src.max_size(), dense_.data());
  242. }
  243. template<typename Value>
  244. SparseArray<Value>::SparseArray(SparseArray&& src)
  245. : size_(src.size_),
  246. sparse_(std::move(src.sparse_)),
  247. dense_(std::move(src.dense_)) {
  248. src.size_ = 0;
  249. }
  250. template<typename Value>
  251. SparseArray<Value>& SparseArray<Value>::operator=(const SparseArray& src) {
  252. // Construct these first for exception safety.
  253. PODArray<int> a(src.max_size());
  254. PODArray<IndexValue> b(src.max_size());
  255. size_ = src.size_;
  256. sparse_ = std::move(a);
  257. dense_ = std::move(b);
  258. std::copy_n(src.sparse_.data(), src.max_size(), sparse_.data());
  259. std::copy_n(src.dense_.data(), src.max_size(), dense_.data());
  260. return *this;
  261. }
  262. template<typename Value>
  263. SparseArray<Value>& SparseArray<Value>::operator=(SparseArray&& src) {
  264. size_ = src.size_;
  265. sparse_ = std::move(src.sparse_);
  266. dense_ = std::move(src.dense_);
  267. src.size_ = 0;
  268. return *this;
  269. }
  270. // IndexValue pairs: exposed in SparseArray::iterator.
  271. template<typename Value>
  272. class SparseArray<Value>::IndexValue {
  273. public:
  274. int index() const { return index_; }
  275. Value& value() { return value_; }
  276. const Value& value() const { return value_; }
  277. private:
  278. friend class SparseArray;
  279. int index_;
  280. Value value_;
  281. };
  282. // Change the maximum size of the array.
  283. // Invalidates all iterators.
  284. template<typename Value>
  285. void SparseArray<Value>::resize(int new_max_size) {
  286. DebugCheckInvariants();
  287. if (new_max_size > max_size()) {
  288. const int old_max_size = max_size();
  289. // Construct these first for exception safety.
  290. PODArray<int> a(new_max_size);
  291. PODArray<IndexValue> b(new_max_size);
  292. std::copy_n(sparse_.data(), old_max_size, a.data());
  293. std::copy_n(dense_.data(), old_max_size, b.data());
  294. sparse_ = std::move(a);
  295. dense_ = std::move(b);
  296. MaybeInitializeMemory(old_max_size, new_max_size);
  297. }
  298. if (size_ > new_max_size)
  299. size_ = new_max_size;
  300. DebugCheckInvariants();
  301. }
  302. // Check whether index i is in the array.
  303. template<typename Value>
  304. bool SparseArray<Value>::has_index(int i) const {
  305. assert(i >= 0);
  306. assert(i < max_size());
  307. if (static_cast<uint32_t>(i) >= static_cast<uint32_t>(max_size())) {
  308. return false;
  309. }
  310. // Unsigned comparison avoids checking sparse_[i] < 0.
  311. return (uint32_t)sparse_[i] < (uint32_t)size_ &&
  312. dense_[sparse_[i]].index_ == i;
  313. }
  314. template<typename Value>
  315. void SparseArray<Value>::create_index(int i) {
  316. assert(!has_index(i));
  317. assert(size_ < max_size());
  318. sparse_[i] = size_;
  319. dense_[size_].index_ = i;
  320. size_++;
  321. }
  322. template<typename Value> SparseArray<Value>::SparseArray(int max_size) :
  323. sparse_(max_size), dense_(max_size) {
  324. MaybeInitializeMemory(size_, max_size);
  325. DebugCheckInvariants();
  326. }
  327. template<typename Value> SparseArray<Value>::~SparseArray() {
  328. DebugCheckInvariants();
  329. }
  330. template<typename Value> void SparseArray<Value>::DebugCheckInvariants() const {
  331. assert(0 <= size_);
  332. assert(size_ <= max_size());
  333. }
  334. // Comparison function for sorting.
  335. template<typename Value> bool SparseArray<Value>::less(const IndexValue& a,
  336. const IndexValue& b) {
  337. return a.index_ < b.index_;
  338. }
  339. } // namespace re2
  340. #endif // UTIL_SPARSE_ARRAY_H_