72#ifndef TPL_PERSISTENT_TREAP_H
73#define TPL_PERSISTENT_TREAP_H
94 std::uint64_t x = n + 0x9e3779b97f4a7c15ULL;
95 x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;
96 x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;
100 template <
typename Node,
typename Key,
class Compare>
107 return p ==
nullptr ? 0 : p->count;
112 const Node *curr = node.get();
113 while (curr->left !=
nullptr)
114 curr = curr->left.get();
115 return curr->key.get();
120 const Node *curr = node.get();
121 while (curr->right !=
nullptr)
122 curr = curr->right.get();
123 return curr->key.get();
133 template <
class Rebuild>
136 const NodePtr child = node->left;
141 template <
class Rebuild>
144 const NodePtr child = node->right;
149 template <
class Rebuild>
156 if (right ==
nullptr)
159 if (left->priority <= right->priority)
169 template <
class Rebuild>
182 if (
cmp(key, *node->key))
190 if (
cmp(*node->key, key))
202 template <
class Rebuild>
209 return {
nullptr,
nullptr};
220 return {std::move(
left_left), std::move(right)};
224 requires std::copy_constructible<Key>
229 out.append(Key(*node->key));
241 if (node->key ==
nullptr)
243 if constexpr (
requires (
const Node &n) { n.value; })
244 if (node->value ==
nullptr)
246 if (lo !=
nullptr and not cmp(*lo, *node->key))
248 if (hi !=
nullptr and not cmp(*node->key, *hi))
250 if (node->left !=
nullptr and node->left->priority < node->priority)
252 if (node->right !=
nullptr and node->right->priority < node->priority)
281template <
typename Key,
class Compare = Aleph::less<Key>>
286 std::shared_ptr<const Key>
key;
289 std::shared_ptr<const Node>
left;
301 const std::uint64_t priority,
308 <<
"PersistentTreapSet: node size would overflow";
311 <<
"PersistentTreapSet: node size would overflow";
313 auto node = std::make_shared<Node>();
314 node->key = std::move(key);
315 node->priority = priority;
316 node->left = std::move(left);
317 node->right = std::move(right);
324 return make_node(node->key, node->priority, std::move(left), std::move(right));
328 std::shared_ptr<const Key> key,
329 const std::uint64_t priority,
336 return make_node(std::move(key), priority,
nullptr,
nullptr);
339 if (
cmp(*key, *node->key))
349 if (
cmp(*node->key, *key))
401 while (curr !=
nullptr)
403 curr = curr->
left.get();
404 else if (
cmp_(*curr->
key, key))
405 curr = curr->
right.get();
407 return curr->
key.get();
418 return find(key) !=
nullptr;
429 auto stored_key = std::make_shared<const Key>(key);
430 bool inserted =
false;
445 auto stored_key = std::make_shared<const Key>(std::move(key));
446 bool inserted =
false;
472 [[
nodiscard]] std::pair<PersistentTreapSet, PersistentTreapSet>
493 <<
"PersistentTreapSet::join(): right tree must be ordered by left comparator";
495 <<
"PersistentTreapSet::join(): left keys must be strictly less than right keys";
510 return join(*
this, right);
545template <
typename Key,
typename T,
class Compare = Aleph::less<Key>>
550 std::shared_ptr<const Key>
key;
554 std::shared_ptr<const Node>
left;
566 std::shared_ptr<const T>
value,
567 const std::uint64_t priority,
574 <<
"PersistentTreapMap: node size would overflow";
577 <<
"PersistentTreapMap: node size would overflow";
579 auto node = std::make_shared<Node>();
580 node->key = std::move(key);
581 node->value = std::move(
value);
582 node->priority = priority;
583 node->left = std::move(left);
584 node->right = std::move(right);
591 return make_node(node->key, node->value, node->priority,
592 std::move(left), std::move(right));
596 std::shared_ptr<const Key> key,
597 std::shared_ptr<const T>
value,
598 const std::uint64_t priority,
605 return make_node(std::move(key), std::move(
value), priority,
nullptr,
nullptr);
608 if (
cmp(*key, *node->key))
611 priority,
cmp, inserted);
620 if (
cmp(*node->key, *key))
623 priority,
cmp, inserted);
637 std::shared_ptr<const Key> key,
638 std::shared_ptr<const T>
value,
639 const std::uint64_t priority,
646 return make_node(std::move(key), std::move(
value), priority,
nullptr,
nullptr);
649 if (
cmp(*key, *node->key))
660 if (
cmp(*node->key, *key))
672 return make_node(node->key, std::move(
value), node->priority, node->left, node->right);
676 requires (std::copy_constructible<Key>
and std::copy_constructible<T>)
681 out.append(std::pair<Key, T>{*node->key, *node->value});
723 while (curr !=
nullptr)
725 curr = curr->
left.get();
726 else if (
cmp_(*curr->
key, key))
727 curr = curr->
right.get();
729 return curr->
value.get();
740 return find(key) !=
nullptr;
752 template <
typename KArg,
typename VArg>
753 requires std::constructible_from<Key, KArg &&>
and std::constructible_from<T, VArg &&>
756 auto stored_key = std::make_shared<const Key>(std::forward<KArg>(key));
758 bool inserted =
false;
773 template <
typename KArg,
typename VArg>
774 requires std::constructible_from<Key, KArg &&>
and std::constructible_from<T, VArg &&>
777 auto stored_key = std::make_shared<const Key>(std::forward<KArg>(key));
779 bool inserted =
false;
807 [[
nodiscard]] std::pair<PersistentTreapMap, PersistentTreapMap>
828 <<
"PersistentTreapMap::join(): right tree must be ordered by left comparator";
830 <<
"PersistentTreapMap::join(): left keys must be strictly less than right keys";
845 return join(*
this, right);
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_unless(C)
Throws std::domain_error if condition does NOT hold.
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
Standard functor implementations and comparison objects.
WeightedDigraph::Node Node
size_t size_t int32_t value
size_t size_t int32_t * out
Simple dynamic array with automatic resizing and functional operations.
void reserve(size_t cap)
Reserves cap cells into the array.
Immutable ordered map backed by a path-copying treap.
std::pair< PersistentTreapMap, PersistentTreapMap > split(const Key &pivot) const
Split this version around pivot.
static void collect_items(const NodePtr &node, Array< std::pair< Key, T > > &out)
PersistentTreapMap(NodePtr root, Compare cmp, const std::uint64_t next_priority)
const T * find(const Key &key) const
Find a mapped value.
static NodePtr rebuild_node(const NodePtr &node, NodePtr left, NodePtr right)
and std::constructible_from< T, VArg && > PersistentTreapMap insert_or_assign(KArg &&key, VArg &&value) const
Return a new version with key assigned to value.
bool is_empty() const noexcept
Return true when the map has no bindings.
PersistentTreapMap erase(const Key &key) const
Return a new version without key.
PersistentTreapMap(Compare cmp=Compare())
Construct an empty persistent map.
static NodePtr make_node(std::shared_ptr< const Key > key, std::shared_ptr< const T > value, const std::uint64_t priority, NodePtr left, NodePtr right)
static NodePtr insert_rec(const NodePtr &node, std::shared_ptr< const Key > key, std::shared_ptr< const T > value, const std::uint64_t priority, const Compare &cmp, bool &inserted)
static PersistentTreapMap join(const PersistentTreapMap &left, const PersistentTreapMap &right)
Join two ordered, non-overlapping map versions.
Array< Key > keys() const
Return all keys in sorted order.
std::uint64_t next_priority_
size_t size() const noexcept
Return the number of key/value bindings in this version.
bool verify() const
Verify treap, BST and cached-size invariants.
bool contains(const Key &key) const
Test whether key is present.
Array< std::pair< Key, T > > items() const
Return all key/value bindings in sorted-key order.
static NodePtr insert_or_assign_rec(const NodePtr &node, std::shared_ptr< const Key > key, std::shared_ptr< const T > value, const std::uint64_t priority, const Compare &cmp, bool &inserted)
PersistentTreapMap join(const PersistentTreapMap &right) const
Join this version with right.
std::shared_ptr< const Node > NodePtr
and std::constructible_from< T, VArg && > PersistentTreapMap insert(KArg &&key, VArg &&value) const
Return a new version with a binding inserted if absent.
Immutable ordered set backed by a path-copying treap.
static NodePtr rebuild_node(const NodePtr &node, NodePtr left, NodePtr right)
size_t size() const noexcept
Return the number of keys stored in this version.
Array< Key > keys() const
Return all keys in sorted order.
PersistentTreapSet insert(Key &&key) const
Return a new version with key inserted by move.
static NodePtr insert_rec(const NodePtr &node, std::shared_ptr< const Key > key, const std::uint64_t priority, const Compare &cmp, bool &inserted)
const Key * find(const Key &key) const
Find a key equivalent to key.
bool verify() const
Verify treap, BST and cached-size invariants.
PersistentTreapSet erase(const Key &key) const
Return a new version without key.
std::uint64_t next_priority_
PersistentTreapSet insert(const Key &key) const
Return a new version with key inserted by copy.
std::shared_ptr< const Node > NodePtr
std::pair< PersistentTreapSet, PersistentTreapSet > split(const Key &pivot) const
Split this version around pivot.
bool is_empty() const noexcept
Return true when the set has no keys.
bool contains(const Key &key) const
Test whether key is present.
PersistentTreapSet(Compare cmp=Compare())
Construct an empty persistent set.
static PersistentTreapSet join(const PersistentTreapSet &left, const PersistentTreapSet &right)
Join two ordered, non-overlapping set versions.
PersistentTreapSet(NodePtr root, Compare cmp, const std::uint64_t next_priority)
static NodePtr make_node(std::shared_ptr< const Key > key, const std::uint64_t priority, NodePtr left, NodePtr right)
PersistentTreapSet join(const PersistentTreapSet &right) const
Join this version with right.
__gmp_expr< T, __gmp_binary_expr< __gmp_expr< T, U >, unsigned long int, __gmp_root_function > > root(const __gmp_expr< T, U > &expr, unsigned long int l)
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
std::uint64_t persistent_treap_priority(const std::uint64_t n) noexcept
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
std::decay_t< typename HeadC::Item_Type > T
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
std::shared_ptr< const T > value
std::shared_ptr< const Node > left
std::shared_ptr< const Node > right
std::shared_ptr< const Key > key
std::shared_ptr< const Node > right
std::shared_ptr< const Node > left
std::shared_ptr< const Key > key
static std::pair< NodePtr, NodePtr > split_rec(const NodePtr &node, const Key &pivot, const Compare &cmp, const Rebuild &rebuild)
static NodePtr rotate_left(const NodePtr &node, const Rebuild &rebuild)
static void collect_keys(const NodePtr &node, Array< Key > &out)
std::shared_ptr< const Node > NodePtr
static NodePtr rotate_right(const NodePtr &node, const Rebuild &rebuild)
static const Key * min_key(const NodePtr &node) noexcept
static NodePtr join_nodes(const NodePtr &left, const NodePtr &right, const Rebuild &rebuild)
static size_t node_size(const NodePtr &p) noexcept
static const Key * max_key(const NodePtr &node) noexcept
static bool can_join(const NodePtr &left, const NodePtr &right, const Compare &cmp)
static bool verify_rec(const NodePtr &node, const Key *lo, const Key *hi, const Compare &cmp, size_t &count)
static NodePtr erase_rec(const NodePtr &node, const Key &key, const Compare &cmp, bool &erased, const Rebuild &rebuild)
static bool is_valid_under(const NodePtr &node, const Compare &cmp)
Dynamic array container with automatic resizing.