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