3#include <absl/container/flat_hash_set.h>
14inline static constexpr size_t SizeOf =
sizeof(std::conditional_t<std::is_pointer_v<T>, uintptr_t, T>);
16template<
class T>
class Pool;
22 constexpr Data() noexcept = default;
32 for (
size_t i = 0, e = d1->
size; res && i != e; ++i) res &= d1->
elems[i] == d2->
elems[i];
38 if (!d)
return H::combine(std::move(h), 0);
39 return H::combine_contiguous(std::move(h), d->elems, d->size);
43 static_assert(
sizeof(Data) ==
sizeof(size_t),
"Data.elems should be 0");
48 constexpr PooledSet(
const Data* data) noexcept
55 constexpr
void clear() noexcept { data_ =
nullptr; }
60 constexpr explicit operator bool() const noexcept {
return data_; }
61 constexpr bool empty() const noexcept {
return data_ ==
nullptr; }
62 constexpr size_t size() const noexcept {
return empty() ? 0 : data_->
size; }
64 constexpr const T&
front()
const {
return (*
this)[0]; }
65 constexpr const T*
elems()
const {
return data_ ? data_->
elems :
nullptr; }
77 constexpr auto begin() const noexcept {
return elems(); }
80 constexpr auto cend() const noexcept {
return end(); }
81 constexpr auto rbegin() const noexcept {
return std::reverse_iterator(
end()); }
82 constexpr auto rend() const noexcept {
return std::reverse_iterator(
begin()); }
84 constexpr auto crend() const noexcept {
return rend(); }
88 const Data* data_ =
nullptr;
97template<
class T>
struct std::hash<
mim::PooledSet<T>> {
98 constexpr size_t operator()(
mim::PooledSet<T> set)
const {
return std::hash<uintptr_t>()((uintptr_t)set.data_); }
126 auto [data, state] = allocate(1);
127 data->elems[0] = elem;
128 return unify(data, state);
133 if (a == b || !b)
return a;
136 auto size = a.size() + b.
size();
137 auto [data, state] = allocate(size);
139 auto di = data->elems;
140 auto ai = a.begin(), ae = a.end(), bi = b.
begin(), be = b.
end();
142 *di = (*ai)->gid() < (*bi)->gid() ? *ai++ : *bi++;
144 while (ai != ae && bi != be)
145 if ((*ai)->gid() < (*bi)->gid())
146 copy_if_unique_and_inc(di, ai);
148 copy_if_unique_and_inc(di, bi);
151 while (ai != ae) copy_if_unique_and_inc(di, ai);
152 while (bi != be) copy_if_unique_and_inc(di, bi);
154 auto actual_size = std::distance(data->elems, di + 1);
155 data->size = actual_size;
156 return unify(data, state, size - actual_size);
164 if (!set)
return set;
166 if (i == set.
end())
return set;
168 auto size = set.
size() - 1;
171 auto [data, state] = allocate(size);
172 std::copy(i + 1, set.
end(), std::copy(set.
begin(), i, data->elems));
173 return unify(data, state);
178 if (a == b)
return true;
179 if (!a || !b)
return false;
181 for (
auto ai = a.begin(), ae = a.end(), bi = b.
begin(), be = b.
end(); ai != ae && bi != be;) {
182 if (*ai == *bi)
return true;
184 if ((*ai)->gid() < (*bi)->gid())
196 swap(p1.arena_, p2.arena_);
197 swap(p1.pool_, p2.pool_);
201 std::pair<Data*, fe::Arena::State> allocate(
size_t size) {
202 auto bytes =
sizeof(Data) + size *
SizeOf<T>;
203 auto state = arena_.state();
204 auto buf = arena_.allocate(bytes);
205 auto data =
new (buf) Data(size);
206 return {data, state};
209 PooledSet<T> unify(Data* data, fe::Arena::State state,
size_t excess = 0) {
210 auto [i, ins] = pool_.emplace(data);
213 return PooledSet<T>(data);
216 arena_.deallocate(state);
217 return PooledSet<T>(*i);
220 void copy_if_unique_and_inc(T*& i,
const T*& ai) {
221 if ((*i)->gid() != (*ai)->gid()) *++i = *ai;
226 absl::flat_hash_set<const Data*, absl::Hash<const Data*>,
typename Data::Equal> pool_;
Maintains PooledSets within a fe::Arena and unifies them in a absl::flat_hash_set.
PooledSet< T > singleton(T elem)
PooledSet< T > merge(PooledSet< T > a, PooledSet< T > b)
Yields .
PooledSet< T > erase(PooledSet< T > set, const T &elem)
Yields .
bool has_intersection(PooledSet< T > a, PooledSet< T > b)
Is ?
friend void swap(Pool &p1, Pool &p2) noexcept
Pool(const Pool &)=delete
PooledSet< T > insert(PooledSet< T > a, const T &elem)
Yields .
Pool & operator=(const Pool &)=delete
Ordered set maintained in a consecutive buffer and unified in Pool.
constexpr auto cend() const noexcept
constexpr bool operator==(PooledSet< T > other) const noexcept
constexpr bool operator!=(PooledSet< T > other) const noexcept
constexpr auto crbegin() const noexcept
constexpr auto end() const noexcept
constexpr size_t size() const noexcept
constexpr const T & operator[](size_t i) const
constexpr auto crend() const noexcept
constexpr PooledSet() noexcept=default
constexpr bool contains(const T &elem) const
constexpr auto begin() const noexcept
constexpr auto rbegin() const noexcept
friend H AbslHashValue(H h, PooledSet< T > set)
constexpr bool empty() const noexcept
constexpr const T * elems() const
constexpr void clear() noexcept
constexpr auto rend() const noexcept
constexpr auto cbegin() const noexcept
constexpr const T & front() const
static constexpr size_t SizeOf
I binary_find(I begin, I end, T val, Cmp cmp)
constexpr bool operator()(const Data *d1, const Data *d2) const
friend constexpr H AbslHashValue(H h, const Data *d)
constexpr Data() noexcept=default