/Users/deen/code/yugabyte-db/src/yb/gutil/algorithm.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2006 Google Inc. |
2 | | // |
3 | | // Licensed to the Apache Software Foundation (ASF) under one |
4 | | // or more contributor license agreements. See the NOTICE file |
5 | | // distributed with this work for additional information |
6 | | // regarding copyright ownership. The ASF licenses this file |
7 | | // to you under the Apache License, Version 2.0 (the |
8 | | // "License"); you may not use this file except in compliance |
9 | | // with the License. You may obtain a copy of the License at |
10 | | // |
11 | | // http://www.apache.org/licenses/LICENSE-2.0 |
12 | | // |
13 | | // Unless required by applicable law or agreed to in writing, |
14 | | // software distributed under the License is distributed on an |
15 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
16 | | // KIND, either express or implied. See the License for the |
17 | | // specific language governing permissions and limitations |
18 | | // under the License. |
19 | | // |
20 | | // The following only applies to changes made to this file as part of YugaByte development. |
21 | | // |
22 | | // Portions Copyright (c) YugaByte, Inc. |
23 | | // |
24 | | // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
25 | | // in compliance with the License. You may obtain a copy of the License at |
26 | | // |
27 | | // http://www.apache.org/licenses/LICENSE-2.0 |
28 | | // |
29 | | // Unless required by applicable law or agreed to in writing, software distributed under the License |
30 | | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
31 | | // or implied. See the License for the specific language governing permissions and limitations |
32 | | // under the License. |
33 | | // |
34 | | // --- |
35 | | // |
36 | | // |
37 | | // This file contains some Google extensions to the standard |
38 | | // <algorithm> C++ header. Many of these algorithms were in the |
39 | | // original STL before it was proposed for standardization. |
40 | | |
41 | | #ifndef YB_GUTIL_ALGORITHM_H |
42 | | #define YB_GUTIL_ALGORITHM_H |
43 | | |
44 | | #include <algorithm> |
45 | | #include <functional> |
46 | | |
47 | | using std::copy; |
48 | | using std::max; |
49 | | using std::min; |
50 | | using std::reverse; |
51 | | using std::sort; |
52 | | using std::swap; |
53 | | using std::binary_function; |
54 | | using std::less; |
55 | | using std::back_insert_iterator; |
56 | | using std::iterator_traits; |
57 | | using std::make_pair; |
58 | | using std::pair; |
59 | | |
60 | | namespace util { |
61 | | namespace gtl { |
62 | | |
63 | | // Returns true if [first, last) contains an element equal to value. |
64 | | // Complexity: linear. |
65 | | template<typename InputIterator, typename EqualityComparable> |
66 | | bool contains(InputIterator first, InputIterator last, |
67 | 0 | const EqualityComparable& value) { |
68 | 0 | return std::find(first, last, value) != last; |
69 | 0 | } |
70 | | |
71 | | // There is no contains_if(). Use any() instead. |
72 | | |
73 | | template<typename InputIterator, typename ForwardIterator> |
74 | | bool contains_some_of(InputIterator first1, InputIterator last1, |
75 | | ForwardIterator first2, ForwardIterator last2) { |
76 | | return std::find_first_of(first1, last1, first2, last2) != last1; |
77 | | } |
78 | | |
79 | | template<typename InputIterator, typename ForwardIterator, typename Predicate> |
80 | | bool contains_some_of(InputIterator first1, InputIterator last1, |
81 | | ForwardIterator first2, ForwardIterator last2, |
82 | | Predicate pred) { |
83 | | return std::find_first_of(first1, last1, first2, last2, pred) != last1; |
84 | | } |
85 | | |
86 | | template<typename InputIterator, typename EqualityComparable> |
87 | | typename std::iterator_traits<InputIterator>::pointer |
88 | | find_or_null(InputIterator first, InputIterator last, |
89 | | const EqualityComparable& value) { |
90 | | const InputIterator it = std::find(first, last, value); |
91 | | return it != last ? &*it : NULL; |
92 | | } |
93 | | |
94 | | template<typename InputIterator, typename Predicate> |
95 | | typename std::iterator_traits<InputIterator>::pointer |
96 | | find_if_or_null(InputIterator first, InputIterator last, Predicate pred) { |
97 | | const InputIterator it = std::find_if(first, last, pred); |
98 | | return it != last ? &*it : NULL; |
99 | | } |
100 | | |
101 | | // Copies all elements that satisfy the predicate pred from [first, |
102 | | // last) to out. This is the complement of remove_copy_if. Complexity: |
103 | | // exactly last-first applications of pred. |
104 | | template <typename InputIterator, typename OutputIterator, typename Predicate> |
105 | | OutputIterator copy_if(InputIterator first, InputIterator last, |
106 | | OutputIterator out, |
107 | | Predicate pred) { |
108 | | for (; first != last; ++first) { |
109 | | if (pred(*first)) |
110 | | *out++ = *first; |
111 | | } |
112 | | return out; |
113 | | } |
114 | | |
115 | | // Copies n elements to out. Equivalent to copy(first, first + n, out) for |
116 | | // random access iterators and a longer code block for lesser iterators. |
117 | | template <typename InputIterator, typename Size, typename OutputIterator> |
118 | | OutputIterator copy_n(InputIterator first, Size n, OutputIterator out) { |
119 | | while (n > 0) { |
120 | | *out = *first; |
121 | | ++out; |
122 | | ++first; |
123 | | --n; |
124 | | } |
125 | | return out; |
126 | | } |
127 | | |
128 | | // Returns true if pred is true for every element in [first, last). Complexity: |
129 | | // at most last-first applications of pred. |
130 | | template <typename InputIterator, typename Predicate> |
131 | | bool all(InputIterator first, InputIterator last, Predicate pred) { |
132 | | for (; first != last; ++first) { |
133 | | if (!pred(*first)) |
134 | | return false; |
135 | | } |
136 | | return true; |
137 | | } |
138 | | |
139 | | // Returns true if pred is false for every element in [first, |
140 | | // last). Complexity: at most last-first applications of pred. |
141 | | template <typename InputIterator, typename Predicate> |
142 | | bool none(InputIterator first, InputIterator last, Predicate pred) { |
143 | | return find_if(first, last, pred) == last; |
144 | | } |
145 | | |
146 | | // Returns true if pred is true for at least one element in [first, last). |
147 | | // Complexity: at most last-first applications of pred. |
148 | | template <typename InputIterator, typename Predicate> |
149 | | bool any(InputIterator first, InputIterator last, Predicate pred) { |
150 | | return !none(first, last, pred); |
151 | | } |
152 | | |
153 | | // Returns a pair of iterators p such that p.first points to the |
154 | | // minimum element in the range and p.second points to the maximum, |
155 | | // ordered by comp. Complexity: at most floor((3/2) (N-1)) |
156 | | // comparisons. Postcondition: If the return value is <min, max>, min is |
157 | | // the first iterator i in [first, last) such that comp(*j, *i) is |
158 | | // false for every other iterator j, and max is the last iterator i |
159 | | // such that comp(*i, *j) is false for every other iterator j. Or less |
160 | | // formally, min is the first minimum and max is the last maximum. |
161 | | template <typename ForwardIter, typename Compare> |
162 | | std::pair<ForwardIter, ForwardIter> minmax_element(ForwardIter first, |
163 | | const ForwardIter last, |
164 | | Compare comp) { |
165 | | // Initialization: for N<2, set min=max=first. For N >= 2, set min |
166 | | // to be the smaller of the first two and max to be the larger. (Taking |
167 | | // care that min is the first, and max the second, if the two compare |
168 | | // equivalent.) |
169 | | ForwardIter min(first); |
170 | | ForwardIter max(first); |
171 | | |
172 | | if (first != last) { |
173 | | ++first; |
174 | | } |
175 | | |
176 | | if (first != last) { |
177 | | max = first; |
178 | | if (comp(*max, *min)) |
179 | | swap(min, max); |
180 | | ++first; |
181 | | } |
182 | | |
183 | | while (first != last) { |
184 | | ForwardIter next(first); |
185 | | ++next; |
186 | | |
187 | | if (next != last) { |
188 | | // We have two elements to look at that we haven't seen already, |
189 | | // *first and *next. Compare the smaller of them with the |
190 | | // current min, and the larger against the current max. The |
191 | | // subtle point: write all of the comparisons so that, if the |
192 | | // two things being compared are equivalent, we take the first |
193 | | // one as the smaller and the last as the larger. |
194 | | if (comp(*next, *first)) { |
195 | | if (comp(*next, *min)) |
196 | | min = next; |
197 | | if (!comp(*first, *max)) |
198 | | max = first; |
199 | | } else { |
200 | | if (comp(*first, *min)) |
201 | | min = first; |
202 | | if (!comp(*next, *max)) |
203 | | max = next; |
204 | | } |
205 | | } else { |
206 | | // There is only one element left that we haven't seen already, *first. |
207 | | // Adjust min or max, as appropriate, and exit the loop. |
208 | | if (comp(*first, *min)) { |
209 | | min = first; |
210 | | } else if (!comp(*first, *max)) { |
211 | | max = first; |
212 | | } |
213 | | break; |
214 | | } |
215 | | |
216 | | first = next; |
217 | | ++first; |
218 | | } |
219 | | |
220 | | return make_pair(min, max); |
221 | | } |
222 | | |
223 | | // Returns a pair of iterators p such that p.first points to the first |
224 | | // minimum element in the range and p.second points to the last |
225 | | // maximum, ordered by operator<. |
226 | | template <typename ForwardIter> |
227 | | inline std::pair<ForwardIter, ForwardIter> minmax_element(ForwardIter first, |
228 | | ForwardIter last) { |
229 | | typedef typename std::iterator_traits<ForwardIter>::value_type value_type; |
230 | | return util::gtl::minmax_element(first, last, std::less<value_type>()); |
231 | | } |
232 | | |
233 | | // Returns true if [first, last) is partitioned by pred, i.e. if all |
234 | | // elements that satisfy pred appear before those that do |
235 | | // not. Complexity: linear. |
236 | | template <typename ForwardIterator, typename Predicate> |
237 | | inline bool is_partitioned(ForwardIterator first, ForwardIterator last, |
238 | | Predicate pred) { |
239 | | for (; first != last; ++first) { |
240 | | if (!pred(*first)) { |
241 | | ++first; |
242 | | return util::gtl::none(first, last, pred); |
243 | | } |
244 | | } |
245 | | return true; |
246 | | } |
247 | | |
248 | | // Precondition: is_partitioned(first, last, pred). Returns: the |
249 | | // partition point p, i.e. an iterator mid satisfying the conditions |
250 | | // all(first, mid, pred) and none(mid, last, pred). Complexity: |
251 | | // O(log(last-first)) applications of pred. |
252 | | template <typename ForwardIterator, typename Predicate> |
253 | | ForwardIterator partition_point(ForwardIterator first, ForwardIterator last, |
254 | | Predicate pred) { |
255 | | typedef typename std::iterator_traits<ForwardIterator>::difference_type diff; |
256 | | diff n = distance(first, last); |
257 | | |
258 | | // Loop invariant: n == distance(first, last) |
259 | | while (first != last) { |
260 | | diff half = n/2; |
261 | | ForwardIterator mid = first; |
262 | | advance(mid, half); |
263 | | if (pred(*mid)) { |
264 | | first = mid; |
265 | | ++first; |
266 | | n -= half+1; |
267 | | } else { |
268 | | n = half; |
269 | | last = mid; |
270 | | } |
271 | | } |
272 | | |
273 | | return first; |
274 | | } |
275 | | |
276 | | // Copies all elements that satisfy pred to out_true and all elements |
277 | | // that don't satisfy it to out_false. Returns: a pair p such that |
278 | | // p.first is the end of the range beginning at out_t and p.second is |
279 | | // the end of the range beginning at out_f. Complexity: exactly |
280 | | // last-first applications of pred. |
281 | | template <typename InputIterator, |
282 | | typename OutputIterator1, typename OutputIterator2, |
283 | | typename Predicate> |
284 | | std::pair<OutputIterator1, OutputIterator2> |
285 | | partition_copy(InputIterator first, InputIterator last, |
286 | | OutputIterator1 out_true, OutputIterator2 out_false, |
287 | | Predicate pred) { |
288 | | for (; first != last; ++first) { |
289 | | if (pred(*first)) |
290 | | *out_true++ = *first; |
291 | | else |
292 | | *out_false++ = *first; |
293 | | } |
294 | | return make_pair(out_true, out_false); |
295 | | } |
296 | | |
297 | | // Reorders elements in [first, last), so that for each consecutive group |
298 | | // of duplicate elements (according to eq predicate) the first one is left and |
299 | | // others are moved at the end of the range. Returns: iterator middle such that |
300 | | // [first, middle) contains no two consecutive elements that are duplicates and |
301 | | // [middle, last) contains elements removed from all groups. It's stable for |
302 | | // range [first, middle) meaning the order of elements are the same as order of |
303 | | // their corresponding groups in input, but the order in range [middle, last) |
304 | | // is not preserved. Function is similar to std::unique, but ensures that |
305 | | // removed elements are properly copied and accessible at the range's end. |
306 | | // Complexity: exactly last-first-1 applications of eq; at most middle-first-1 |
307 | | // swap operations. |
308 | | template <typename ForwardIterator, typename Equals> |
309 | | ForwardIterator unique_partition(ForwardIterator first, ForwardIterator last, |
310 | | Equals eq) { |
311 | | first = adjacent_find(first, last, eq); |
312 | | if (first == last) |
313 | | return last; |
314 | | |
315 | | // Points to right-most element within range of unique elements being built. |
316 | | ForwardIterator result = first; |
317 | | |
318 | | // 'first' iterator goes through the sequence starting from element after |
319 | | // first equal elements pair (found by adjacent_find above). |
320 | | ++first; |
321 | | while (++first != last) { |
322 | | // If we encounter an element that isn't equal to right-most element in |
323 | | // result, then extend the range and swap this element into it. |
324 | | // Otherwise just continue incrementing 'first'. |
325 | | if (!eq(*result, *first)) { |
326 | | swap(*++result, *first); |
327 | | } |
328 | | } |
329 | | // Return past-the-end upper-bound of the resulting range. |
330 | | return ++result; |
331 | | } |
332 | | |
333 | | // Reorders elements in [first, last) range moving duplicates for each |
334 | | // consecutive group of elements to the end. Equality is checked using ==. |
335 | | template <typename ForwardIterator> |
336 | | inline ForwardIterator unique_partition(ForwardIterator first, |
337 | | ForwardIterator last) { |
338 | | typedef typename std::iterator_traits<ForwardIterator>::value_type T; |
339 | | return unique_partition(first, last, std::equal_to<T>()); |
340 | | } |
341 | | |
342 | | // Samples k elements from the next n. |
343 | | // Elements have the same order in the output stream as they did on input. |
344 | | // |
345 | | // This is Algorithm S from section 3.4.2 of Knuth, TAOCP, 2nd edition. |
346 | | // My k corresponds to Knuth n-m. |
347 | | // My n corrsponds to Knuth N-t. |
348 | | // |
349 | | // RngFunctor is any functor that can be called as: |
350 | | // size_t RngFunctor(size_t x) |
351 | | // The return value is an integral value in the half-open range [0, x) |
352 | | // such that all values are equally likely. Behavior is unspecified if x==0. |
353 | | // (This function never calls RngFunctor with x==0). |
354 | | |
355 | | template <typename InputIterator, typename OutputIterator, typename RngFunctor> |
356 | | inline void sample_k_of_n(InputIterator in, size_t k, size_t n, |
357 | | RngFunctor& rng, OutputIterator out) { // NOLINT |
358 | | if (k > n) { |
359 | | k = n; |
360 | | } |
361 | | while (k > 0) { |
362 | | if (rng(n) < k) { |
363 | | *out++ = *in; |
364 | | k--; |
365 | | } |
366 | | ++in; |
367 | | --n; |
368 | | } |
369 | | } |
370 | | |
371 | | // Finds the longest prefix of a range that is a binary max heap with |
372 | | // respect to a given StrictWeakOrdering. If first == last, returns last. |
373 | | // Otherwise, return an iterator it such that [first,it) is a heap but |
374 | | // no longer prefix is -- in other words, first + i for the lowest i |
375 | | // such that comp(first[(i-1)/2], first[i]) returns true. |
376 | | template <typename RandomAccessIterator, typename StrictWeakOrdering> |
377 | | RandomAccessIterator gtl_is_binary_heap_until(RandomAccessIterator first, |
378 | | RandomAccessIterator last, |
379 | | StrictWeakOrdering comp) { |
380 | | if (last - first < 2) return last; |
381 | | RandomAccessIterator parent = first; |
382 | | bool is_right_child = false; |
383 | | for (RandomAccessIterator child = first + 1; child != last; ++child) { |
384 | | if (comp(*parent, *child)) return child; |
385 | | if (is_right_child) ++parent; |
386 | | is_right_child = !is_right_child; |
387 | | } |
388 | | return last; |
389 | | } |
390 | | |
391 | | // Special case of gtl_is_binary_heap_until where the order is std::less, |
392 | | // i.e., where we're working with a simple max heap. |
393 | | template <typename RandomAccessIterator> |
394 | | RandomAccessIterator gtl_is_binary_heap_until(RandomAccessIterator first, |
395 | | RandomAccessIterator last) { |
396 | | typedef typename std::iterator_traits<RandomAccessIterator>::value_type T; |
397 | | return gtl_is_binary_heap_until(first, last, std::less<T>()); |
398 | | } |
399 | | |
400 | | // Checks whether a range of values is a binary heap, i.e., checks that |
401 | | // no node is less (as defined by a StrictWeakOrdering) than a child. |
402 | | template <typename RandomAccessIterator, typename StrictWeakOrdering> |
403 | | bool gtl_is_binary_heap(RandomAccessIterator begin, |
404 | | RandomAccessIterator end, |
405 | | StrictWeakOrdering comp) { |
406 | | return gtl_is_binary_heap_until(begin, end, comp) == end; |
407 | | } |
408 | | |
409 | | // Special case of gtl_is_binary_heap where the order is std::less (i.e., |
410 | | // where we're working on a simple max heap). |
411 | | template <typename RandomAccessIterator> |
412 | | bool gtl_is_binary_heap(RandomAccessIterator begin, |
413 | | RandomAccessIterator end) { |
414 | | return gtl_is_binary_heap_until(begin, end) == end; |
415 | | } |
416 | | |
417 | | // Unqualified calls to is_heap are ambiguous with some build types, |
418 | | // namespace that can clash with names that C++11 added to ::std. |
419 | | // By calling util::gtl::is_heap, clients can avoid those errors, |
420 | | // and by using the underlying is_heap call we ensure consistency |
421 | | // with the standard library's heap implementation just in case a |
422 | | // standard library ever uses anything other than a binary heap. |
423 | | #if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus > 199711L \ |
424 | | || defined(LIBCXX) || _MSC_VER >= 1600 /* Visual Studio 2010 */ |
425 | | using std::is_heap; |
426 | | #elif defined __GNUC__ |
427 | | /* using __gnu_cxx::is_heap; */ |
428 | | #elif defined _MSC_VER |
429 | | // For old versions of MSVC++, we know by inspection that make_heap() |
430 | | // traffics in binary max heaps, so gtl_is_binary_heap is an acceptable |
431 | | // implementation for is_heap. |
432 | | template <typename RandomAccessIterator> |
433 | | bool is_heap(RandomAccessIterator begin, RandomAccessIterator end) { |
434 | | return gtl_is_binary_heap(begin, end); |
435 | | } |
436 | | |
437 | | template <typename RandomAccessIterator, typename StrictWeakOrdering> |
438 | | bool is_heap(RandomAccessIterator begin, |
439 | | RandomAccessIterator end, |
440 | | StrictWeakOrdering comp) { |
441 | | return gtl_is_binary_heap(begin, end, comp); |
442 | | } |
443 | | #else |
444 | | // We need an implementation of is_heap that matches the library's |
445 | | // implementation of make_heap() and friends. gtl_is_binary_heap will |
446 | | // *probably* work, but let's be safe and not make that assumption. |
447 | | #error No implementation of is_heap defined for this toolchain. |
448 | | #endif |
449 | | |
450 | | } // namespace gtl |
451 | | } // namespace util |
452 | | |
453 | | #endif // YB_GUTIL_ALGORITHM_H |