27 typename MemoryPolicy,
33 typename MemoryPolicy,
40 using owner_t =
typename MemoryPolicy::transience_t::owner;
63 for (
auto&& v : values)
68 template <
typename Iter,
typename Sent,
70 <compatible_sentinel_v<Iter, Sent>,
bool> =
true>
75 for (; first != last; ++first)
153 assert(r ==
nullptr || r->d.count);
155 r ? r->d.sizes[r->d.count - 1] :
160 template <
typename Visitor,
typename... Args>
173 template <
typename Visitor,
typename... Args>
174 void traverse(Visitor v,
size_t first,
size_t last, Args&&... args)
const 179 if (first < tail_off)
182 last < tail_off ? last : tail_off,
187 first > tail_off ? first - tail_off : 0,
192 template <
typename Visitor,
typename... Args>
205 template <
typename Visitor,
typename... Args>
206 bool traverse_p(Visitor v,
size_t first,
size_t last, Args&&... args)
const 214 last < tail_off ? last : tail_off,
220 first > tail_off ? first - tail_off : 0,
226 template <
typename Visitor>
227 decltype(
auto)
descend(Visitor v,
size_t idx)
const 230 return idx >= tail_off
235 template <
typename Fn>
241 template <
typename Fn>
247 template <
typename Fn>
253 template <
typename Fn>
262 if (
size != other.
size)
return false;
263 if (
size == 0)
return true;
267 if (tail_off > 0 && tail_off_other > 0) {
281 other.
root, other.
shift, tail_off_other))
289 tail_off > tail_off_other ? std::equal(
291 other.
tail->
leaf() + (tail_off - tail_off_other))
294 iter_t{other} + tail_off);
297 std::tuple<shift_t, node_t*>
305 return {
shift, new_root };
310 new_root->inner() [0] =
root->
inc();
311 new_root->
inner() [1] = new_path;
314 new_root->relaxed()->d.count = 2u;
319 return {
shift + B, new_root };
321 }
else if (
size ==
size_t{branches<B>} <<
shift) {
325 new_root->inner() [0] =
root->
inc();
326 new_root->
inner() [1] = new_path;
331 return {
shift + B, new_root };
335 return {
shift, new_root };
353 new_root->inner() [0] =
root;
354 new_root->
inner() [1] = new_path;
355 new_root->
relaxed()->d.sizes [0] = tail_off;
356 new_root->relaxed()->d.sizes [1] = tail_off +
tail_size;
357 new_root->relaxed()->d.count = 2u;
365 }
else if (tail_off ==
size_t{branches<B>} <<
shift) {
369 new_root->inner() [0] =
root;
370 new_root->
inner() [1] = new_path;
377 }
else if (tail_off) {
400 if (ts < branches<BL>) {
402 new (&
tail->
leaf()[ts]) T{std::move(value)};
421 if (ts < branches<BL>) {
433 return {
size + 1, get<0>(new_root), get<1>(new_root), new_tail };
441 std::tuple<const T*, size_t, size_t>
446 if (idx >= tail_off) {
452 auto first = idx - get<1>(subs);
453 auto end = first + get<2>(subs);
454 return { get<0>(subs), first, end };
461 if (idx >= tail_off) {
463 return tail->
leaf() [(idx - tail_off) & mask<BL>];
471 const T&
get(
size_t index)
const 479 throw std::out_of_range{
"out of range"};
490 return get(
size - 1);
493 template <
typename FnT>
497 elem = std::forward<FnT>(fn) (std::move(elem));
500 template <
typename FnT>
504 if (idx >= tail_off) {
520 return std::move(value);
526 return update(idx, [&] (
auto&&) {
527 return std::move(value);
536 }
else if (new_size >=
size) {
538 }
else if (new_size > tail_off) {
539 auto ts =
size - tail_off;
540 auto newts = new_size - tail_off;
552 auto l = new_size - 1;
555 auto new_shift = get<0>(r);
556 auto new_root = get<1>(r);
557 auto new_tail = get<3>(r);
577 }
else if (new_size >=
size) {
579 }
else if (new_size > tail_off) {
584 auto l = new_size - 1;
587 auto new_shift = get<0>(r);
588 auto new_root = get<1>(r);
589 auto new_tail = get<3>(r);
591 assert(new_root->compute_shift() == get<0>(r));
592 assert(new_root->check(new_shift, new_size - get<2>(r)));
593 return { new_size, new_shift, new_root, new_tail };
606 }
else if (elems >=
size) {
608 }
else if (elems == tail_off) {
614 }
else if (elems > tail_off) {
617 v, elems - tail_off, e));
639 }
else if (elems >=
size) {
652 auto new_root = get<1>(r);
653 auto new_shift = get<0>(r);
654 return {
size - elems, new_shift, new_root,
tail->
inc() };
661 assert(r.
size < (std::numeric_limits<size_t>::max() -
size));
665 else if (r.
size == 0)
675 return {
size + r.
size, get<0>(new_root), get<1>(new_root),
682 auto remaining = branches<BL> -
tail_size;
689 add_tail, branches<BL>);
691 get<0>(new_root), get<1>(new_root),
707 auto new_shift = concated.shift();
708 auto new_root = concated.node();
709 assert(new_shift == new_root->compute_shift());
718 auto new_shift = concated.shift();
719 auto new_root = concated.node();
720 assert(new_shift == new_root->compute_shift());
727 !std::is_empty<edit_t>::value;
732 assert(r.
size < (std::numeric_limits<size_t>::max() - l.
size));
736 else if (r.
size == 0)
755 auto remaining = branches<BL> -
tail_size;
783 MemoryPolicy::transience_t::noone,
785 assert(concated.shift() == concated.node()->compute_shift());
786 assert(concated.node()->check(concated.shift(), l.
size + r.
tail_offset()));
788 l.
shift = concated.shift();
789 l.
root = concated.node();
796 l = { l.
size + r.
size, concated.shift(),
797 concated.node(), r.
tail->
inc() };
807 MemoryPolicy::transience_t::noone,
809 assert(concated.shift() == concated.node()->compute_shift());
810 assert(concated.node()->check(concated.shift(), l.
size + r.
tail_offset()));
812 l.
shift = concated.shift();
813 l.
root = concated.node();
821 l = { l.
size + r.
size, concated.shift(),
822 concated.node(), r.
tail->
inc() };
830 assert(r.
size < (std::numeric_limits<size_t>::max() - l.
size));
834 else if (l.
size == 0)
849 r = { l.
size + r.
size, get<0>(res), get<1>(res),
866 auto remaining = branches<BL> -
tail_size;
877 add_tail, branches<BL>);
879 get<0>(new_root), get<1>(new_root),
900 assert(concated.shift() == concated.node()->compute_shift());
901 assert(concated.node()->check(concated.shift(), l.
size + r.
tail_offset()));
903 r.
shift = concated.shift();
904 r.
root = concated.node();
910 r = { l.
size + r.size, concated.shift(),
911 concated.node(), r.tail->inc() };
920 MemoryPolicy::transience_t::noone,
923 assert(concated.shift() == concated.node()->compute_shift());
924 assert(concated.node()->check(concated.shift(), l.
size + r.
tail_offset()));
926 r.
shift = concated.shift();
927 r.
root = concated.node();
935 r = { l.
size + r.size, concated.shift(),
936 concated.node(), r.tail->inc() };
945 assert(r.
size < (std::numeric_limits<size_t>::max() - l.
size));
949 else if (r.
size == 0)
973 auto remaining = branches<BL> -
tail_size;
1007 assert(concated.shift() == concated.node()->compute_shift());
1008 assert(concated.node()->check(concated.shift(), l.
size + r.
tail_offset()));
1010 l.
shift = concated.shift();
1011 l.
root = concated.node();
1019 l = { l.
size + r.
size, concated.shift(),
1020 concated.node(), r.
tail->
inc() };
1031 assert(concated.shift() == concated.node()->compute_shift());
1032 assert(concated.node()->check(concated.shift(), l.
size + r.
tail_offset()));
1034 l.
shift = concated.shift();
1035 l.
root = concated.node();
1044 l = { l.
size + r.
size, concated.shift(),
1045 concated.node(), r.
tail->
inc() };
1053 assert(r.
size < (std::numeric_limits<size_t>::max() - l.
size));
1057 else if (l.
size == 0)
1069 r = { l.
size + r.
size, get<0>(res), get<1>(res),
1088 auto remaining = branches<BL> -
tail_size;
1099 add_tail, branches<BL>);
1101 get<0>(new_root), get<1>(new_root),
1122 assert(concated.shift() == concated.node()->compute_shift());
1123 assert(concated.node()->check(concated.shift(), l.
size + r.
tail_offset()));
1125 r.
shift = concated.shift();
1126 r.
root = concated.node();
1133 r = { l.
size + r.size, concated.shift(),
1134 concated.node(), r.tail->inc() };
1145 assert(concated.shift() == concated.node()->compute_shift());
1146 assert(concated.node()->check(concated.shift(), l.
size + r.
tail_offset()));
1148 r.
shift = concated.shift();
1149 r.
root = concated.node();
1157 r = { l.
size + r.size, concated.shift(),
1158 concated.node(), r.tail->inc() };
1166 auto&& empty_ =
empty();
1168 shift = empty_.shift;
1175 assert(
shift <=
sizeof(
size_t) * 8 - BL);
1176 assert(
shift >= BL);
1179 #if IMMER_DEBUG_DEEP_CHECK 1188 #if IMMER_DEBUG_DEEP_CHECK 1197 #if IMMER_DEBUG_DEEP_CHECK 1202 assert(
shift == BL);
1208 #if IMMER_DEBUG_PRINT 1209 void debug_print(std::ostream& out)
const 1212 <<
"--" << std::endl
1214 <<
" size = " <<
size << std::endl
1215 <<
" shift = " <<
shift << std::endl
1216 <<
" root = " << std::endl;
1218 out <<
" tail = " << std::endl;
1220 out <<
"}" << std::endl;
1223 void debug_print_indent(std::ostream& out,
unsigned indent)
const 1225 while (indent --> 0)
1229 void debug_print_node(std::ostream& out,
1233 unsigned indent = 8)
const 1235 const auto indent_step = 4;
1237 if (
shift == endshift<B, BL>) {
1238 debug_print_indent(out, indent);
1239 out <<
"- {" <<
size <<
"} " 1240 << pretty_print_array(node->leaf(),
size)
1242 }
else if (
auto r = node->relaxed()) {
1243 auto count = r->d.count;
1244 debug_print_indent(out, indent);
1245 out <<
"# {" <<
size <<
"} " 1246 << pretty_print_array(r->d.sizes, r->d.count)
1248 auto last_size =
size_t{};
1250 debug_print_node(out,
1253 r->d.sizes[i] - last_size,
1254 indent + indent_step);
1255 last_size = r->d.sizes[i];
1258 debug_print_indent(out, indent);
1259 out <<
"+ {" <<
size <<
"}" << std::endl;
1264 debug_print_node(out,
1268 indent + indent_step);
1269 debug_print_node(out,
1270 node->inner()[
count - 1],
1273 indent + indent_step);
1277 #endif // IMMER_DEBUG_PRINT
friend void concat_mut_l(rrbtree &l, edit_t el, const rrbtree &r)
bool for_each_chunk_p(Fn &&fn) const
static auto from_fill(size_t n, T v)
regular_sub_pos< NodeT > make_regular_sub_pos(NodeT *node, shift_t shift, size_t size)
void destroy_n(T *p, Size n)
friend void concat_mut_lr_l(rrbtree &l, edit_t el, rrbtree &r, edit_t er)
static void delete_inner(node_t *p, count_t n)
relaxed_pos< NodeT > make_relaxed_pos(NodeT *node, shift_t shift, typename NodeT::relaxed_t *relaxed)
void update_mut(edit_t e, size_t idx, FnT &&fn)
void traverse(Visitor v, Args &&... args) const
std::tuple< shift_t, node_t * > push_tail(node_t *root, shift_t shift, size_t size, node_t *tail, count_t tail_size) const
void take_mut(edit_t e, size_t new_size)
static node_t * make_path_e(edit_t e, shift_t shift, node_t *node)
static node_t * copy_leaf_emplace(node_t *src, count_t n, U &&x)
empty_regular_pos< NodeT > make_empty_regular_pos(NodeT *node)
static node_t * make_inner_e(edit_t e)
relaxed_pos< Node > concat_trees_mut(edit_type< Node > ec, edit_type< Node > el, Node *lroot, shift_t lshift, size_t lsize, Node *ltail, count_t ltcount, edit_type< Node > er, Node *rroot, shift_t rshift, size_t rsize)
bool check(shift_t shift, size_t size)
typename node_t::edit_t edit_t
SinkIter uninitialized_copy(Iterator first, Sentinel last, SinkIter d_first)
static node_t * copy_leaf_e(edit_t e, node_t *src, count_t n)
static const rrbtree & empty()
static auto from_initializer_list(std::initializer_list< U > values)
bool traverse_p(Visitor v, Args &&... args) const
void push_back_mut(edit_t e, T value)
const T & get_check(size_t index) const
void ensure_mutable_tail(edit_t e, count_t n)
void dec_empty_regular(NodeT *node)
rrbtree(size_t sz, shift_t sh, node_t *r, node_t *t)
decltype(auto) visit_maybe_relaxed_descent(NodeT *node, shift_t shift, Visitor v, size_t idx)
decltype(auto) descend(Visitor v, size_t idx) const
rrbtree(const rrbtree &other)
static node_t * make_inner_n(count_t n)
static node_t * make_leaf_e(edit_t e)
bool traverse_p(Visitor v, size_t first, size_t last, Args &&... args) const
void push_tail_mut(edit_t e, size_t tail_off, node_t *tail, count_t tail_size)
static void delete_inner_r(node_t *p, count_t n)
friend void concat_mut_r(const rrbtree &l, rrbtree &r, edit_t er)
rrbtree & operator=(const rrbtree &other)
void dec_leaf(NodeT *node, count_t n)
static node_t * make_inner_r_e(edit_t e)
typename MemoryPolicy::transience_t::owner owner_t
static void delete_inner_r_e(node_t *p)
rrbtree push_back(T value) const
static void delete_inner_e(node_t *p)
friend void concat_mut_lr_r(rrbtree &l, edit_t el, rrbtree &r, edit_t er)
void for_each_chunk(size_t first, size_t last, Fn &&fn) const
leaf_descent_pos< NodeT > make_leaf_descent_pos(NodeT *node)
static void delete_leaf(node_t *p, count_t n)
auto uninitialized_move(Iter1 in1, Iter1 in2, Iter2 out)
static node_t * make_inner_r_n(count_t n)
rrbtree update(size_t idx, FnT &&fn) const
friend void swap(rrbtree &x, rrbtree &y)
rrbtree drop(size_t elems) const
T & get_mut(edit_t e, size_t idx)
node< T, MemoryPolicy, B, BL > node_t
rrbtree & operator=(rrbtree &&other)
void traverse(Visitor v, size_t first, size_t last, Args &&... args) const
std::tuple< const T *, size_t, size_t > region_for(size_t idx) const
rrbtree concat(const rrbtree &r) const
relaxed_pos< Node > concat_trees(Node *lroot, shift_t lshift, size_t lsize, Node *ltail, count_t ltcount, Node *rroot, shift_t rshift, size_t rsize)
static node_t * copy_leaf(node_t *src, count_t n)
bool equals(const rrbtree &other) const
void assoc_mut(edit_t e, size_t idx, T value)
static constexpr bool supports_transient_concat
static auto from_range(Iter first, Sent last)
empty_leaf_pos< NodeT > make_empty_leaf_pos(NodeT *node)
void drop_mut(edit_t e, size_t elems)
void for_each_chunk(Fn &&fn) const
static node_t * make_leaf_n(count_t n)
bool can_mutate(edit_t e) const
bool for_each_chunk_p(size_t first, size_t last, Fn &&fn) const
void dec_inner(NodeT *node, shift_t shift, size_t size)
decltype(auto) visit_maybe_relaxed_sub(NodeT *node, shift_t shift, size_t size, Visitor v, Args &&...args)
typename transience::edit edit_t
rrbtree take(size_t new_size) const
leaf_sub_pos< NodeT > make_leaf_sub_pos(NodeT *node, count_t count)
static node_t * make_path(shift_t shift, node_t *node)
rrbtree assoc(size_t idx, T value) const