25 #ifndef RS_LAZY_FLAT_SET
26 #define RS_LAZY_FLAT_SET
30 #include <type_traits>
36 template <
class Value,
class Less>
39 template <
class Value,
class Less = std::less<Value>,
class Equal = std::equal_to<Value>,
class Sort = LazyFlatSetQuickSort<Value, Less>,
class Alloc = std::allocator<Value>,
bool IsPo
inter = false>
45 template <
class T>
struct is_pointer : std::conditional<IsPointer || std::is_pointer<T>::value || is_shared_ptr<T>::value, std::true_type, std::false_type>::type {};
47 using base_collection =
typename std::vector<Value, Alloc>;
48 using size_type =
typename base_collection::size_type;
49 using iterator =
typename base_collection::iterator;
50 using const_iterator =
typename base_collection::const_iterator;
51 using value_type = Value;
52 using value_type_ptr =
typename std::conditional<is_pointer<value_type>::value, value_type, value_type*>::type;
53 using reference =
typename std::conditional<std::is_fundamental<value_type>::value || std::is_pointer<value_type>::value, value_type, value_type&>::type;
54 using const_reference =
typename std::conditional<std::is_fundamental<value_type>::value || std::is_pointer<value_type>::value, value_type,
const value_type&>::type;
55 using less_type = Less;
56 using equal_type = Equal;
57 using sort_type = Sort;
58 using alloc_type = Alloc;
59 using compare_type =
typename std::function<int(const_reference)>;
60 using erase_type =
typename std::function<void(reference)>;
62 LazyFlatSet(
unsigned maxUnsortedEntries = 16,
unsigned maxNurseryEntries = 1024) :
63 maxUnsortedEntries_(maxUnsortedEntries), maxNurseryEntries_(maxNurseryEntries) {
64 unsorted_.reserve(maxUnsortedEntries);
67 void insert(
const value_type& k) {
68 auto iter = lower_bound_equals(coll_, k);
69 if (iter != coll_.end()) {
72 iter = lower_bound_equals(nursery_, k);
73 if (iter != nursery_.end()) {
76 iter = search_unsorted(unsorted_, k);
77 if (iter != unsorted_.end()) {
80 if (unsorted_.size() == maxUnsortedEntries_) {
84 unsorted_.push_back(k);
90 template <
typename... Args>
91 void emplace(Args&&... args) {
92 if (unsorted_.size() == maxUnsortedEntries_) {
96 unsorted_.emplace_back(std::forward<Args>(args)...);
98 auto iter = lower_bound_equals(coll_, unsorted_.back());
99 if (iter != coll_.end()) {
100 *iter = std::move(unsorted_.back());
101 unsorted_.pop_back();
103 iter = lower_bound_equals(nursery_, unsorted_.back());
104 if (iter != nursery_.end()) {
105 *iter = std::move(unsorted_.back());
106 unsorted_.pop_back();
107 }
else if (unsorted_.size() > 1) {
108 auto newItemIter = unsorted_.end() - 1;
110 iter = search_unsorted(unsorted_, unsorted_.back());
111 if (iter != newItemIter) {
112 *iter = std::move(unsorted_.back());
113 unsorted_.pop_back();
120 return coll_.empty() && nursery_.empty() && unsorted_.empty();
129 void clear_fn(erase_type erase) {
130 for (
auto i : coll_) {
136 for (
auto i : nursery_) {
142 for (
auto i : unsorted_) {
149 void reserve(size_type n) {
153 size_type size()
const {
154 return coll_.size() + nursery_.size() + unsorted_.size();
157 void shrink_to_fit() {
159 nursery_.shrink_to_fit();
160 coll_.shrink_to_fit();
163 size_type count(
const value_type& k)
const {
166 auto iter = lower_bound_equals(coll_, k);
167 if (iter != coll_.end()) {
170 iter = lower_bound_equals(nursery_, k);
171 if (iter != nursery_.end()) {
174 iter = search_unsorted(unsorted_, k);
175 if (iter != unsorted_.end()) {
184 size_type count_fn(compare_type compare)
const {
187 auto index = search(coll_, compare);
188 if (index != search_end) {
191 index = search(nursery_, compare);
192 if (index != search_end) {
195 index = search_unsorted(unsorted_, compare);
196 if (index != search_end) {
205 bool find(
const value_type& k, value_type& v)
const {
208 auto iter = lower_bound_equals(coll_, k);
209 if (iter != coll_.end()) {
213 iter = lower_bound_equals(nursery_, k);
214 if (iter != nursery_.end()) {
218 iter = search_unsorted(unsorted_, k);
219 if (iter != unsorted_.end()) {
229 value_type_ptr find_fn(compare_type compare)
const {
230 value_type_ptr value =
nullptr;
232 auto index = search(coll_, compare);
233 if (index != search_end) {
234 value = getValue(coll_, index, is_pointer<value_type>());
236 index = search(nursery_, compare);
237 if (index != search_end) {
238 value = getValue(nursery_, index, is_pointer<value_type>());
240 index = search_unsorted(unsorted_, compare);
241 if (index != search_end) {
242 value = getValue(unsorted_, index, is_pointer<value_type>());
250 const_reference operator[](size_type n)
const {
255 const_iterator cbegin()
const {
257 return coll_.cbegin();
260 const_iterator cend()
const {
265 const value_type* data()
const {
270 size_type erase(
const value_type& k) {
273 auto iter = lower_bound_equals(coll_, k);
274 if (iter != coll_.end()) {
278 iter = lower_bound_equals(nursery_, k);
279 if (iter != nursery_.end()) {
280 nursery_.erase(iter);
283 iter = search_unsorted(unsorted_, k);
284 if (iter != unsorted_.end()) {
285 unsorted_.erase(iter);
294 size_type erase_fn(compare_type compare, erase_type erase =
nullptr) {
297 auto index = search(coll_, compare);
298 if (index != search_end) {
299 if (erase !=
nullptr) {
302 coll_.erase(coll_.begin() + index);
305 index = search(nursery_, compare);
306 if (index != search_end) {
307 if (erase !=
nullptr) {
308 erase(nursery_[index]);
310 nursery_.erase(nursery_.begin() + index);
313 index = search_unsorted(unsorted_, compare);
314 if (index != search_end) {
315 if (erase !=
nullptr) {
316 erase(unsorted_[index]);
318 unsorted_.erase(unsorted_.begin() + index);
327 void copy(std::vector<Value>& coll,
bool sort =
true)
const {
332 const auto newSize = coll.size() + coll_.size() + nursery_.size() + unsorted_.size();
333 coll.reserve(newSize);
335 coll.insert(coll.end(), coll_.cbegin(), coll_.cend());
336 coll.insert(coll.end(), nursery_.cbegin(), nursery_.cend());
337 coll.insert(coll.end(), unsorted_.cbegin(), unsorted_.cend());
341 const size_type search_end = -1;
343 void sort(base_collection& coll)
const {
344 Sort{}(coll.begin(), coll.end());
347 iterator lower_bound(base_collection& coll,
const value_type& k)
const {
348 return std::lower_bound(coll.begin(), coll.end(), k, Less{});
351 iterator lower_bound_equals(base_collection& coll,
const value_type& k)
const {
352 auto iter = lower_bound(coll, k);
353 return iter != coll.end() && Equal{}(*iter, k) ? iter : coll.end();
356 iterator upper_bound(base_collection& coll,
const value_type& k)
const {
357 return std::upper_bound(coll.begin(), coll.end(), k, Less{});
360 iterator upper_bound_equals(base_collection& coll,
const value_type& k)
const {
361 auto iter = upper_bound(coll, k);
362 return iter != coll.end() && Equal{}(*iter, k) ? iter : coll.end();
365 size_type search(base_collection& coll, compare_type compare)
const {
366 const auto size = coll.size();
370 size_type
max = size - 1;
371 const auto data = coll.data();
373 while (max != search_end && max >= min) {
374 auto mid = ((max - min) / 2) + min;
376 const auto& item = data[mid];
377 auto diff = compare(item);
380 }
else if (diff < 0) {
391 size_type search_unsorted(base_collection& coll, compare_type compare)
const {
392 const auto data = coll.data();
394 for (size_type i = 0, size = coll.size(); i < size; ++i) {
395 if (compare(data[i]) == 0) {
403 iterator search_unsorted(base_collection& coll,
const value_type& k)
const {
404 return std::search_n(coll.begin(), coll.end(), 1, k, Equal{});
412 void flushUnsorted()
const {
413 const auto unsortedSize = unsorted_.size();
414 if (unsortedSize > 0) {
415 if ((nursery_.size() + unsortedSize) > maxNurseryEntries_) {
420 merge(unsorted_, nursery_);
425 void flushNursery()
const {
426 if (nursery_.size() > 0) {
427 merge(nursery_, coll_);
432 void merge(base_collection& source, base_collection& target)
const {
433 if (source.size() > 0) {
435 if (target.size() == 0 || less(target.back(), source.front())) {
436 target.insert(target.end(), source.cbegin(), source.cend());
437 }
else if (less(source.back(), target.front())) {
438 target.insert(target.begin(), source.cbegin(), source.cend());
440 target.insert(target.begin(), source.cbegin(), source.cend());
441 std::inplace_merge(target.begin(), target.begin() + source.size(), target.end(), less);
446 value_type getValue(base_collection& coll,
int index, std::true_type)
const {
450 value_type_ptr getValue(base_collection& coll,
int index, std::false_type)
const {
454 const unsigned maxUnsortedEntries_;
455 const unsigned maxNurseryEntries_;
457 mutable base_collection coll_;
458 mutable base_collection nursery_;
459 mutable base_collection unsorted_;
462 template <
class Value,
class Less>
463 struct LazyFlatSetQuickSort {
464 void operator()(
typename LazyFlatSet<Value>::iterator first,
typename LazyFlatSet<Value>::iterator last) {
465 std::sort(first, last, Less{});
const atl::Variable< T > min(const atl::Variable< T > &a, const atl::Variable< T > &b)
Definition: ATL.hpp:57
Definition: lazyflatset.hpp:40
Definition: ad_cmath.hpp:17
Definition: lazyflatset.hpp:45
Definition: lazyflatset.hpp:34
Definition: lazyflatset.hpp:42
Definition: lazyflatset.hpp:37
const atl::Variable< T > max(const atl::Variable< T > &a, const atl::Variable< T > &b)
Definition: ATL.hpp:43