diff options
Diffstat (limited to 'third_party/immer/immer/detail/rbts/position.hpp')
-rw-r--r-- | third_party/immer/immer/detail/rbts/position.hpp | 1977 |
1 files changed, 0 insertions, 1977 deletions
diff --git a/third_party/immer/immer/detail/rbts/position.hpp b/third_party/immer/immer/detail/rbts/position.hpp deleted file mode 100644 index e9472b2940..0000000000 --- a/third_party/immer/immer/detail/rbts/position.hpp +++ /dev/null @@ -1,1977 +0,0 @@ -// -// immer: immutable data structures for C++ -// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente -// -// This software is distributed under the Boost Software License, Version 1.0. -// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt -// - -#pragma once - -#include <immer/config.hpp> -#include <immer/detail/rbts/bits.hpp> - -#include <cassert> -#include <type_traits> -#include <utility> - -namespace immer { -namespace detail { -namespace rbts { - -template <typename Pos> -constexpr auto bits = std::decay_t<Pos>::node_t::bits; - -template <typename Pos> -constexpr auto bits_leaf = std::decay_t<Pos>::node_t::bits_leaf; - -template <typename Pos> -using node_type = typename std::decay<Pos>::type::node_t; - -template <typename Pos> -using edit_type = typename std::decay<Pos>::type::node_t::edit_t; - -template <typename NodeT> -struct empty_regular_pos -{ - using node_t = NodeT; - node_t* node_; - - count_t count() const { return 0; } - node_t* node() const { return node_; } - shift_t shift() const { return 0; } - size_t size() const { return 0; } - - template <typename Visitor, typename... Args> - void each(Visitor, Args&&...) - {} - template <typename Visitor, typename... Args> - bool each_pred(Visitor, Args&&...) - { - return true; - } - - template <typename Visitor, typename... Args> - decltype(auto) visit(Visitor v, Args&&... args) - { - return Visitor::visit_regular(*this, std::forward<Args>(args)...); - } -}; - -template <typename NodeT> -empty_regular_pos<NodeT> make_empty_regular_pos(NodeT* node) -{ - return {node}; -} - -template <typename NodeT> -struct empty_leaf_pos -{ - using node_t = NodeT; - node_t* node_; - - count_t count() const { return 0; } - node_t* node() const { return node_; } - shift_t shift() const { return 0; } - size_t size() const { return 0; } - - template <typename Visitor, typename... Args> - decltype(auto) visit(Visitor v, Args&&... args) - { - return Visitor::visit_leaf(*this, std::forward<Args>(args)...); - } -}; - -template <typename NodeT> -empty_leaf_pos<NodeT> make_empty_leaf_pos(NodeT* node) -{ - assert(node); - return {node}; -} - -template <typename NodeT> -struct leaf_pos -{ - static constexpr auto B = NodeT::bits; - static constexpr auto BL = NodeT::bits_leaf; - - using node_t = NodeT; - node_t* node_; - size_t size_; - - count_t count() const { return index(size_ - 1) + 1; } - node_t* node() const { return node_; } - size_t size() const { return size_; } - shift_t shift() const { return 0; } - count_t index(size_t idx) const { return idx & mask<BL>; } - count_t subindex(size_t idx) const { return idx; } - - template <typename Visitor, typename... Args> - decltype(auto) visit(Visitor v, Args&&... args) - { - return Visitor::visit_leaf(*this, std::forward<Args>(args)...); - } -}; - -template <typename NodeT> -leaf_pos<NodeT> make_leaf_pos(NodeT* node, size_t size) -{ - assert(node); - assert(size > 0); - return {node, size}; -} - -template <typename NodeT> -struct leaf_sub_pos -{ - static constexpr auto B = NodeT::bits; - static constexpr auto BL = NodeT::bits_leaf; - - using node_t = NodeT; - node_t* node_; - count_t count_; - - count_t count() const { return count_; } - node_t* node() const { return node_; } - size_t size() const { return count_; } - shift_t shift() const { return 0; } - count_t index(size_t idx) const { return idx & mask<BL>; } - count_t subindex(size_t idx) const { return idx; } - - template <typename Visitor, typename... Args> - decltype(auto) visit(Visitor v, Args&&... args) - { - return Visitor::visit_leaf(*this, std::forward<Args>(args)...); - } -}; - -template <typename NodeT> -leaf_sub_pos<NodeT> make_leaf_sub_pos(NodeT* node, count_t count) -{ - assert(node); - assert(count <= branches<NodeT::bits_leaf>); - return {node, count}; -} - -template <typename NodeT> -struct leaf_descent_pos -{ - static constexpr auto B = NodeT::bits; - static constexpr auto BL = NodeT::bits_leaf; - - using node_t = NodeT; - node_t* node_; - - node_t* node() const { return node_; } - shift_t shift() const { return 0; } - count_t index(size_t idx) const { return idx & mask<BL>; } - - template <typename... Args> - decltype(auto) descend(Args&&...) - {} - - template <typename Visitor, typename... Args> - decltype(auto) visit(Visitor v, Args&&... args) - { - return Visitor::visit_leaf(*this, std::forward<Args>(args)...); - } -}; - -template <typename NodeT> -leaf_descent_pos<NodeT> make_leaf_descent_pos(NodeT* node) -{ - assert(node); - return {node}; -} - -template <typename NodeT> -struct full_leaf_pos -{ - static constexpr auto B = NodeT::bits; - static constexpr auto BL = NodeT::bits_leaf; - - using node_t = NodeT; - node_t* node_; - - count_t count() const { return branches<BL>; } - node_t* node() const { return node_; } - size_t size() const { return branches<BL>; } - shift_t shift() const { return 0; } - count_t index(size_t idx) const { return idx & mask<BL>; } - count_t subindex(size_t idx) const { return idx; } - - template <typename Visitor, typename... Args> - decltype(auto) visit(Visitor v, Args&&... args) - { - return Visitor::visit_leaf(*this, std::forward<Args>(args)...); - } -}; - -template <typename NodeT> -full_leaf_pos<NodeT> make_full_leaf_pos(NodeT* node) -{ - assert(node); - return {node}; -} - -template <typename NodeT> -struct regular_pos -{ - static constexpr auto B = NodeT::bits; - static constexpr auto BL = NodeT::bits_leaf; - - using node_t = NodeT; - node_t* node_; - shift_t shift_; - size_t size_; - - count_t count() const { return index(size_ - 1) + 1; } - node_t* node() const { return node_; } - size_t size() const { return size_; } - shift_t shift() const { return shift_; } - count_t index(size_t idx) const { return (idx >> shift_) & mask<B>; } - count_t subindex(size_t idx) const { return idx >> shift_; } - size_t this_size() const - { - return ((size_ - 1) & ~(~size_t{} << (shift_ + B))) + 1; - } - - template <typename Visitor, typename... Args> - void each(Visitor v, Args&&... args) - { - return each_regular(*this, v, args...); - } - - template <typename Visitor, typename... Args> - bool each_pred(Visitor v, Args&&... args) - { - return each_pred_regular(*this, v, args...); - } - - template <typename Visitor, typename... Args> - bool each_pred_zip(Visitor v, node_t* other, Args&&... args) - { - return each_pred_zip_regular(*this, v, other, args...); - } - - template <typename Visitor, typename... Args> - bool each_pred_i(Visitor v, count_t i, count_t n, Args&&... args) - { - return each_pred_i_regular(*this, v, i, n, args...); - } - - template <typename Visitor, typename... Args> - bool each_pred_right(Visitor v, count_t start, Args&&... args) - { - return each_pred_right_regular(*this, v, start, args...); - } - - template <typename Visitor, typename... Args> - bool each_pred_left(Visitor v, count_t n, Args&&... args) - { - return each_pred_left_regular(*this, v, n, args...); - } - - template <typename Visitor, typename... Args> - void each_i(Visitor v, count_t i, count_t n, Args&&... args) - { - return each_i_regular(*this, v, i, n, args...); - } - - template <typename Visitor, typename... Args> - void each_right(Visitor v, count_t start, Args&&... args) - { - return each_right_regular(*this, v, start, args...); - } - - template <typename Visitor, typename... Args> - void each_left(Visitor v, count_t n, Args&&... args) - { - return each_left_regular(*this, v, n, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) towards(Visitor v, size_t idx, Args&&... args) - { - return towards_oh_ch_regular( - *this, v, idx, index(idx), count(), args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) - towards_oh(Visitor v, size_t idx, count_t offset_hint, Args&&... args) - { - return towards_oh_ch_regular( - *this, v, idx, offset_hint, count(), args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) towards_oh_ch(Visitor v, - size_t idx, - count_t offset_hint, - count_t count_hint, - Args&&... args) - { - return towards_oh_ch_regular( - *this, v, idx, offset_hint, count(), args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) - towards_sub_oh(Visitor v, size_t idx, count_t offset_hint, Args&&... args) - { - return towards_sub_oh_regular(*this, v, idx, offset_hint, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) last_oh(Visitor v, count_t offset_hint, Args&&... args) - { - return last_oh_regular(*this, v, offset_hint, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) visit(Visitor v, Args&&... args) - { - return Visitor::visit_regular(*this, std::forward<Args>(args)...); - } -}; - -template <typename Pos, typename Visitor, typename... Args> -void each_regular(Pos&& p, Visitor v, Args&&... args) -{ - constexpr auto B = bits<Pos>; - constexpr auto BL = bits_leaf<Pos>; - auto n = p.node()->inner(); - auto last = p.count() - 1; - auto e = n + last; - if (p.shift() == BL) { - for (; n != e; ++n) { - IMMER_PREFETCH(n + 1); - make_full_leaf_pos(*n).visit(v, args...); - } - make_leaf_pos(*n, p.size()).visit(v, args...); - } else { - auto ss = p.shift() - B; - for (; n != e; ++n) - make_full_pos(*n, ss).visit(v, args...); - make_regular_pos(*n, ss, p.size()).visit(v, args...); - } -} - -template <typename Pos, typename Visitor, typename... Args> -bool each_pred_regular(Pos&& p, Visitor v, Args&&... args) -{ - constexpr auto B = bits<Pos>; - constexpr auto BL = bits_leaf<Pos>; - auto n = p.node()->inner(); - auto last = p.count() - 1; - auto e = n + last; - if (p.shift() == BL) { - for (; n != e; ++n) { - IMMER_PREFETCH(n + 1); - if (!make_full_leaf_pos(*n).visit(v, args...)) - return false; - } - return make_leaf_pos(*n, p.size()).visit(v, args...); - } else { - auto ss = p.shift() - B; - for (; n != e; ++n) - if (!make_full_pos(*n, ss).visit(v, args...)) - return false; - return make_regular_pos(*n, ss, p.size()).visit(v, args...); - } -} - -template <typename Pos, typename Visitor, typename... Args> -bool each_pred_zip_regular(Pos&& p, - Visitor v, - node_type<Pos>* other, - Args&&... args) -{ - constexpr auto B = bits<Pos>; - constexpr auto BL = bits_leaf<Pos>; - - auto n = p.node()->inner(); - auto n2 = other->inner(); - auto last = p.count() - 1; - auto e = n + last; - if (p.shift() == BL) { - for (; n != e; ++n, ++n2) { - IMMER_PREFETCH(n + 1); - IMMER_PREFETCH(n2 + 1); - if (!make_full_leaf_pos(*n).visit(v, *n2, args...)) - return false; - } - return make_leaf_pos(*n, p.size()).visit(v, *n2, args...); - } else { - auto ss = p.shift() - B; - for (; n != e; ++n, ++n2) - if (!make_full_pos(*n, ss).visit(v, *n2, args...)) - return false; - return make_regular_pos(*n, ss, p.size()).visit(v, *n2, args...); - } -} - -template <typename Pos, typename Visitor, typename... Args> -bool each_pred_i_regular( - Pos&& p, Visitor v, count_t f, count_t l, Args&&... args) -{ - constexpr auto B = bits<Pos>; - constexpr auto BL = bits_leaf<Pos>; - - if (p.shift() == BL) { - if (l > f) { - if (l < p.count()) { - auto n = p.node()->inner() + f; - auto e = p.node()->inner() + l; - for (; n < e; ++n) { - IMMER_PREFETCH(n + 1); - if (!make_full_leaf_pos(*n).visit(v, args...)) - return false; - } - } else { - auto n = p.node()->inner() + f; - auto e = p.node()->inner() + l - 1; - for (; n < e; ++n) { - IMMER_PREFETCH(n + 1); - if (!make_full_leaf_pos(*n).visit(v, args...)) - return false; - } - if (!make_leaf_pos(*n, p.size()).visit(v, args...)) - return false; - } - } - } else { - if (l > f) { - auto ss = p.shift() - B; - if (l < p.count()) { - auto n = p.node()->inner() + f; - auto e = p.node()->inner() + l; - for (; n < e; ++n) - if (!make_full_pos(*n, ss).visit(v, args...)) - return false; - } else { - auto n = p.node()->inner() + f; - auto e = p.node()->inner() + l - 1; - for (; n < e; ++n) - if (!make_full_pos(*n, ss).visit(v, args...)) - return false; - if (!make_regular_pos(*n, ss, p.size()).visit(v, args...)) - return false; - } - } - } - return true; -} - -template <typename Pos, typename Visitor, typename... Args> -bool each_pred_left_regular(Pos&& p, Visitor v, count_t last, Args&&... args) -{ - constexpr auto B = bits<Pos>; - constexpr auto BL = bits_leaf<Pos>; - assert(last < p.count()); - if (p.shift() == BL) { - auto n = p.node()->inner(); - auto e = n + last; - for (; n != e; ++n) { - IMMER_PREFETCH(n + 1); - if (!make_full_leaf_pos(*n).visit(v, args...)) - return false; - } - } else { - auto n = p.node()->inner(); - auto e = n + last; - auto ss = p.shift() - B; - for (; n != e; ++n) - if (!make_full_pos(*n, ss).visit(v, args...)) - return false; - } - return true; -} - -template <typename Pos, typename Visitor, typename... Args> -bool each_pred_right_regular(Pos&& p, Visitor v, count_t start, Args&&... args) -{ - constexpr auto B = bits<Pos>; - constexpr auto BL = bits_leaf<Pos>; - - if (p.shift() == BL) { - auto n = p.node()->inner() + start; - auto last = p.count() - 1; - auto e = p.node()->inner() + last; - if (n <= e) { - for (; n != e; ++n) { - IMMER_PREFETCH(n + 1); - if (!make_full_leaf_pos(*n).visit(v, args...)) - return false; - } - if (!make_leaf_pos(*n, p.size()).visit(v, args...)) - return false; - } - } else { - auto n = p.node()->inner() + start; - auto last = p.count() - 1; - auto e = p.node()->inner() + last; - auto ss = p.shift() - B; - if (n <= e) { - for (; n != e; ++n) - if (!make_full_pos(*n, ss).visit(v, args...)) - return false; - if (!make_regular_pos(*n, ss, p.size()).visit(v, args...)) - return false; - } - } - return true; -} - -template <typename Pos, typename Visitor, typename... Args> -void each_i_regular(Pos&& p, Visitor v, count_t f, count_t l, Args&&... args) -{ - constexpr auto B = bits<Pos>; - constexpr auto BL = bits_leaf<Pos>; - - if (p.shift() == BL) { - if (l > f) { - if (l < p.count()) { - auto n = p.node()->inner() + f; - auto e = p.node()->inner() + l; - for (; n < e; ++n) { - IMMER_PREFETCH(n + 1); - make_full_leaf_pos(*n).visit(v, args...); - } - } else { - auto n = p.node()->inner() + f; - auto e = p.node()->inner() + l - 1; - for (; n < e; ++n) { - IMMER_PREFETCH(n + 1); - make_full_leaf_pos(*n).visit(v, args...); - } - make_leaf_pos(*n, p.size()).visit(v, args...); - } - } - } else { - if (l > f) { - auto ss = p.shift() - B; - if (l < p.count()) { - auto n = p.node()->inner() + f; - auto e = p.node()->inner() + l; - for (; n < e; ++n) - make_full_pos(*n, ss).visit(v, args...); - } else { - auto n = p.node()->inner() + f; - auto e = p.node()->inner() + l - 1; - for (; n < e; ++n) - make_full_pos(*n, ss).visit(v, args...); - make_regular_pos(*n, ss, p.size()).visit(v, args...); - } - } - } -} - -template <typename Pos, typename Visitor, typename... Args> -void each_left_regular(Pos&& p, Visitor v, count_t last, Args&&... args) -{ - constexpr auto B = bits<Pos>; - constexpr auto BL = bits_leaf<Pos>; - assert(last < p.count()); - if (p.shift() == BL) { - auto n = p.node()->inner(); - auto e = n + last; - for (; n != e; ++n) { - IMMER_PREFETCH(n + 1); - make_full_leaf_pos(*n).visit(v, args...); - } - } else { - auto n = p.node()->inner(); - auto e = n + last; - auto ss = p.shift() - B; - for (; n != e; ++n) - make_full_pos(*n, ss).visit(v, args...); - } -} - -template <typename Pos, typename Visitor, typename... Args> -void each_right_regular(Pos&& p, Visitor v, count_t start, Args&&... args) -{ - constexpr auto B = bits<Pos>; - constexpr auto BL = bits_leaf<Pos>; - - if (p.shift() == BL) { - auto n = p.node()->inner() + start; - auto last = p.count() - 1; - auto e = p.node()->inner() + last; - if (n <= e) { - for (; n != e; ++n) { - IMMER_PREFETCH(n + 1); - make_full_leaf_pos(*n).visit(v, args...); - } - make_leaf_pos(*n, p.size()).visit(v, args...); - } - } else { - auto n = p.node()->inner() + start; - auto last = p.count() - 1; - auto e = p.node()->inner() + last; - auto ss = p.shift() - B; - if (n <= e) { - for (; n != e; ++n) - make_full_pos(*n, ss).visit(v, args...); - make_regular_pos(*n, ss, p.size()).visit(v, args...); - } - } -} - -template <typename Pos, typename Visitor, typename... Args> -decltype(auto) towards_oh_ch_regular(Pos&& p, - Visitor v, - size_t idx, - count_t offset_hint, - count_t count_hint, - Args&&... args) -{ - constexpr auto B = bits<Pos>; - constexpr auto BL = bits_leaf<Pos>; - assert(offset_hint == p.index(idx)); - assert(count_hint == p.count()); - auto is_leaf = p.shift() == BL; - auto child = p.node()->inner()[offset_hint]; - auto is_full = offset_hint + 1 != count_hint; - return is_full - ? (is_leaf ? make_full_leaf_pos(child).visit(v, idx, args...) - : make_full_pos(child, p.shift() - B) - .visit(v, idx, args...)) - : (is_leaf - ? make_leaf_pos(child, p.size()).visit(v, idx, args...) - : make_regular_pos(child, p.shift() - B, p.size()) - .visit(v, idx, args...)); -} - -template <typename Pos, typename Visitor, typename... Args> -decltype(auto) towards_sub_oh_regular( - Pos&& p, Visitor v, size_t idx, count_t offset_hint, Args&&... args) -{ - constexpr auto B = bits<Pos>; - constexpr auto BL = bits_leaf<Pos>; - assert(offset_hint == p.index(idx)); - auto is_leaf = p.shift() == BL; - auto child = p.node()->inner()[offset_hint]; - auto lsize = offset_hint << p.shift(); - auto size = p.this_size(); - auto is_full = (size - lsize) >= (size_t{1} << p.shift()); - return is_full - ? (is_leaf - ? make_full_leaf_pos(child).visit(v, idx - lsize, args...) - : make_full_pos(child, p.shift() - B) - .visit(v, idx - lsize, args...)) - : (is_leaf - ? make_leaf_sub_pos(child, size - lsize) - .visit(v, idx - lsize, args...) - : make_regular_sub_pos(child, p.shift() - B, size - lsize) - .visit(v, idx - lsize, args...)); -} - -template <typename Pos, typename Visitor, typename... Args> -decltype(auto) -last_oh_regular(Pos&& p, Visitor v, count_t offset_hint, Args&&... args) -{ - assert(offset_hint == p.count() - 1); - constexpr auto B = bits<Pos>; - constexpr auto BL = bits_leaf<Pos>; - auto child = p.node()->inner()[offset_hint]; - auto is_leaf = p.shift() == BL; - return is_leaf ? make_leaf_pos(child, p.size()).visit(v, args...) - : make_regular_pos(child, p.shift() - B, p.size()) - .visit(v, args...); -} - -template <typename NodeT> -regular_pos<NodeT> make_regular_pos(NodeT* node, shift_t shift, size_t size) -{ - assert(node); - assert(shift >= NodeT::bits_leaf); - assert(size > 0); - return {node, shift, size}; -} - -struct null_sub_pos -{ - auto node() const { return nullptr; } - - template <typename Visitor, typename... Args> - void each_sub(Visitor, Args&&...) - {} - template <typename Visitor, typename... Args> - void each_right_sub(Visitor, Args&&...) - {} - template <typename Visitor, typename... Args> - void each_left_sub(Visitor, Args&&...) - {} - template <typename Visitor, typename... Args> - void visit(Visitor, Args&&...) - {} -}; - -template <typename NodeT> -struct singleton_regular_sub_pos -{ - // this is a fake regular pos made out of a single child... useful - // to treat a single leaf node as a whole tree - - static constexpr auto B = NodeT::bits; - static constexpr auto BL = NodeT::bits_leaf; - - using node_t = NodeT; - node_t* leaf_; - count_t count_; - - count_t count() const { return 1; } - node_t* node() const { return nullptr; } - size_t size() const { return count_; } - shift_t shift() const { return BL; } - count_t index(size_t idx) const { return 0; } - count_t subindex(size_t idx) const { return 0; } - size_t size_before(count_t offset) const { return 0; } - size_t this_size() const { return count_; } - size_t size(count_t offset) { return count_; } - - template <typename Visitor, typename... Args> - void each_left_sub(Visitor v, Args&&... args) - {} - template <typename Visitor, typename... Args> - void each(Visitor v, Args&&... args) - {} - - template <typename Visitor, typename... Args> - decltype(auto) last_sub(Visitor v, Args&&... args) - { - return make_leaf_sub_pos(leaf_, count_).visit(v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) visit(Visitor v, Args&&... args) - { - return Visitor::visit_regular(*this, std::forward<Args>(args)...); - } -}; - -template <typename NodeT> -auto make_singleton_regular_sub_pos(NodeT* leaf, count_t count) -{ - assert(leaf); - IMMER_ASSERT_TAGGED(leaf->kind() == NodeT::kind_t::leaf); - assert(count > 0); - return singleton_regular_sub_pos<NodeT>{leaf, count}; -} - -template <typename NodeT> -struct regular_sub_pos -{ - static constexpr auto B = NodeT::bits; - static constexpr auto BL = NodeT::bits_leaf; - - using node_t = NodeT; - node_t* node_; - shift_t shift_; - size_t size_; - - count_t count() const { return subindex(size_ - 1) + 1; } - node_t* node() const { return node_; } - size_t size() const { return size_; } - shift_t shift() const { return shift_; } - count_t index(size_t idx) const { return (idx >> shift_) & mask<B>; } - count_t subindex(size_t idx) const { return idx >> shift_; } - size_t size_before(count_t offset) const { return offset << shift_; } - size_t this_size() const { return size_; } - - auto size(count_t offset) - { - return offset == subindex(size_ - 1) ? size_ - size_before(offset) - : size_t{1} << shift_; - } - - auto size_sbh(count_t offset, size_t size_before_hint) - { - assert(size_before_hint == size_before(offset)); - return offset == subindex(size_ - 1) ? size_ - size_before_hint - : size_t{1} << shift_; - } - - void copy_sizes(count_t offset, count_t n, size_t init, size_t* sizes) - { - if (n) { - auto last = offset + n - 1; - auto e = sizes + n - 1; - for (; sizes != e; ++sizes) - init = *sizes = init + (size_t{1} << shift_); - *sizes = init + size(last); - } - } - - template <typename Visitor, typename... Args> - void each(Visitor v, Args&&... args) - { - return each_regular(*this, v, args...); - } - - template <typename Visitor, typename... Args> - bool each_pred(Visitor v, Args&&... args) - { - return each_pred_regular(*this, v, args...); - } - - template <typename Visitor, typename... Args> - bool each_pred_zip(Visitor v, node_t* other, Args&&... args) - { - return each_pred_zip_regular(*this, v, other, args...); - } - - template <typename Visitor, typename... Args> - bool each_pred_i(Visitor v, count_t i, count_t n, Args&&... args) - { - return each_pred_i_regular(*this, v, i, n, args...); - } - - template <typename Visitor, typename... Args> - bool each_pred_right(Visitor v, count_t start, Args&&... args) - { - return each_pred_right_regular(*this, v, start, args...); - } - - template <typename Visitor, typename... Args> - bool each_pred_left(Visitor v, count_t last, Args&&... args) - { - return each_pred_left_regular(*this, v, last, args...); - } - - template <typename Visitor, typename... Args> - void each_i(Visitor v, count_t i, count_t n, Args&&... args) - { - return each_i_regular(*this, v, i, n, args...); - } - - template <typename Visitor, typename... Args> - void each_right(Visitor v, count_t start, Args&&... args) - { - return each_right_regular(*this, v, start, args...); - } - - template <typename Visitor, typename... Args> - void each_left(Visitor v, count_t last, Args&&... args) - { - return each_left_regular(*this, v, last, args...); - } - - template <typename Visitor, typename... Args> - void each_right_sub_(Visitor v, count_t i, Args&&... args) - { - auto last = count() - 1; - auto lsize = size_ - (last << shift_); - auto n = node()->inner() + i; - auto e = node()->inner() + last; - if (shift() == BL) { - for (; n != e; ++n) { - IMMER_PREFETCH(n + 1); - make_full_leaf_pos(*n).visit(v, args...); - } - make_leaf_sub_pos(*n, lsize).visit(v, args...); - } else { - auto ss = shift_ - B; - for (; n != e; ++n) - make_full_pos(*n, ss).visit(v, args...); - make_regular_sub_pos(*n, ss, lsize).visit(v, args...); - } - } - - template <typename Visitor, typename... Args> - void each_sub(Visitor v, Args&&... args) - { - each_right_sub_(v, 0, args...); - } - - template <typename Visitor, typename... Args> - void each_right_sub(Visitor v, Args&&... args) - { - if (count() > 1) - each_right_sub_(v, 1, args...); - } - - template <typename Visitor, typename... Args> - void each_left_sub(Visitor v, Args&&... args) - { - each_left(v, count() - 1, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) towards(Visitor v, size_t idx, Args&&... args) - { - return towards_oh_ch_regular( - *this, v, idx, index(idx), count(), args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) - towards_oh(Visitor v, size_t idx, count_t offset_hint, Args&&... args) - { - return towards_oh_ch_regular( - *this, v, idx, offset_hint, count(), args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) towards_oh_ch(Visitor v, - size_t idx, - count_t offset_hint, - count_t count_hint, - Args&&... args) - { - return towards_oh_ch_regular( - *this, v, idx, offset_hint, count(), args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) - towards_sub_oh(Visitor v, size_t idx, count_t offset_hint, Args&&... args) - { - return towards_sub_oh_regular(*this, v, idx, offset_hint, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) last_oh(Visitor v, count_t offset_hint, Args&&... args) - { - return last_oh_regular(*this, v, offset_hint, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) last_sub(Visitor v, Args&&... args) - { - auto offset = count() - 1; - auto child = node_->inner()[offset]; - auto is_leaf = shift_ == BL; - auto lsize = size_ - (offset << shift_); - return is_leaf ? make_leaf_sub_pos(child, lsize).visit(v, args...) - : make_regular_sub_pos(child, shift_ - B, lsize) - .visit(v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) first_sub(Visitor v, Args&&... args) - { - auto is_leaf = shift_ == BL; - auto child = node_->inner()[0]; - auto is_full = size_ >= (size_t{1} << shift_); - return is_full - ? (is_leaf - ? make_full_leaf_pos(child).visit(v, args...) - : make_full_pos(child, shift_ - B).visit(v, args...)) - : (is_leaf - ? make_leaf_sub_pos(child, size_).visit(v, args...) - : make_regular_sub_pos(child, shift_ - B, size_) - .visit(v, args...)); - } - - template <typename Visitor, typename... Args> - decltype(auto) first_sub_leaf(Visitor v, Args&&... args) - { - assert(shift_ == BL); - auto child = node_->inner()[0]; - auto is_full = size_ >= branches<BL>; - return is_full ? make_full_leaf_pos(child).visit(v, args...) - : make_leaf_sub_pos(child, size_).visit(v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) first_sub_inner(Visitor v, Args&&... args) - { - assert(shift_ >= BL); - auto child = node_->inner()[0]; - auto is_full = size_ >= branches<BL>; - return is_full ? make_full_pos(child, shift_ - B).visit(v, args...) - : make_regular_sub_pos(child, shift_ - B, size_) - .visit(v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) nth_sub(count_t idx, Visitor v, Args&&... args) - { - assert(idx < count()); - auto is_leaf = shift_ == BL; - auto child = node_->inner()[idx]; - auto lsize = size(idx); - auto is_full = idx + 1 < count(); - return is_full - ? (is_leaf - ? make_full_leaf_pos(child).visit(v, args...) - : make_full_pos(child, shift_ - B).visit(v, args...)) - : (is_leaf - ? make_leaf_sub_pos(child, lsize).visit(v, args...) - : make_regular_sub_pos(child, shift_ - B, lsize) - .visit(v, args...)); - } - - template <typename Visitor, typename... Args> - decltype(auto) nth_sub_leaf(count_t idx, Visitor v, Args&&... args) - { - assert(shift_ == BL); - auto child = node_->inner()[idx]; - auto lsize = size(idx); - auto is_full = idx + 1 < count(); - return is_full ? make_full_leaf_pos(child).visit(v, args...) - : make_leaf_sub_pos(child, lsize).visit(v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) visit(Visitor v, Args&&... args) - { - return Visitor::visit_regular(*this, std::forward<Args>(args)...); - } -}; - -template <typename NodeT> -regular_sub_pos<NodeT> -make_regular_sub_pos(NodeT* node, shift_t shift, size_t size) -{ - assert(node); - assert(shift >= NodeT::bits_leaf); - assert(size > 0); - assert(size <= (branches<NodeT::bits, size_t> << shift)); - return {node, shift, size}; -} - -template <typename NodeT, - shift_t Shift, - bits_t B = NodeT::bits, - bits_t BL = NodeT::bits_leaf> -struct regular_descent_pos -{ - static_assert(Shift > 0, "not leaf..."); - - using node_t = NodeT; - node_t* node_; - - node_t* node() const { return node_; } - shift_t shift() const { return Shift; } - count_t index(size_t idx) const - { -#if !defined(_MSC_VER) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshift-count-overflow" -#endif - return (idx >> Shift) & mask<B>; -#if !defined(_MSC_VER) -#pragma GCC diagnostic pop -#endif - } - - template <typename Visitor> - decltype(auto) descend(Visitor v, size_t idx) - { - auto offset = index(idx); - auto child = node_->inner()[offset]; - return regular_descent_pos<NodeT, Shift - B>{child}.visit(v, idx); - } - - template <typename Visitor, typename... Args> - decltype(auto) visit(Visitor v, Args&&... args) - { - return Visitor::visit_regular(*this, std::forward<Args>(args)...); - } -}; - -template <typename NodeT, bits_t B, bits_t BL> -struct regular_descent_pos<NodeT, BL, B, BL> -{ - using node_t = NodeT; - node_t* node_; - - node_t* node() const { return node_; } - shift_t shift() const { return BL; } - count_t index(size_t idx) const { return (idx >> BL) & mask<B>; } - - template <typename Visitor> - decltype(auto) descend(Visitor v, size_t idx) - { - auto offset = index(idx); - auto child = node_->inner()[offset]; - return make_leaf_descent_pos(child).visit(v, idx); - } - - template <typename Visitor, typename... Args> - decltype(auto) visit(Visitor v, Args&&... args) - { - return Visitor::visit_regular(*this, std::forward<Args>(args)...); - } -}; - -template <typename NodeT, typename Visitor> -decltype(auto) -visit_regular_descent(NodeT* node, shift_t shift, Visitor v, size_t idx) -{ - constexpr auto B = NodeT::bits; - constexpr auto BL = NodeT::bits_leaf; - assert(node); - assert(shift >= BL); - switch (shift) { - case BL + B * 0: - return regular_descent_pos<NodeT, BL + B * 0>{node}.visit(v, idx); - case BL + B * 1: - return regular_descent_pos<NodeT, BL + B * 1>{node}.visit(v, idx); - case BL + B * 2: - return regular_descent_pos<NodeT, BL + B * 2>{node}.visit(v, idx); - case BL + B * 3: - return regular_descent_pos<NodeT, BL + B * 3>{node}.visit(v, idx); - case BL + B * 4: - return regular_descent_pos<NodeT, BL + B * 4>{node}.visit(v, idx); - case BL + B * 5: - return regular_descent_pos<NodeT, BL + B * 5>{node}.visit(v, idx); -#if IMMER_DESCENT_DEEP - default: - for (auto level = shift; level != endshift<B, BL>; level -= B) - node = node->inner()[(idx >> level) & mask<B>]; - return make_leaf_descent_pos(node).visit(v, idx); -#endif // IMMER_DEEP_DESCENT - } - IMMER_UNREACHABLE; -} - -template <typename NodeT> -struct full_pos -{ - static constexpr auto B = NodeT::bits; - static constexpr auto BL = NodeT::bits_leaf; - - using node_t = NodeT; - node_t* node_; - shift_t shift_; - - count_t count() const { return branches<B>; } - node_t* node() const { return node_; } - size_t size() const { return branches<B> << shift_; } - shift_t shift() const { return shift_; } - count_t index(size_t idx) const { return (idx >> shift_) & mask<B>; } - count_t subindex(size_t idx) const { return idx >> shift_; } - size_t size(count_t offset) const { return size_t{1} << shift_; } - size_t size_sbh(count_t offset, size_t) const - { - return size_t{1} << shift_; - } - size_t size_before(count_t offset) const { return offset << shift_; } - - void copy_sizes(count_t offset, count_t n, size_t init, size_t* sizes) - { - auto e = sizes + n; - for (; sizes != e; ++sizes) - init = *sizes = init + (size_t{1} << shift_); - } - - template <typename Visitor, typename... Args> - void each(Visitor v, Args&&... args) - { - auto p = node_->inner(); - auto e = p + branches<B>; - if (shift_ == BL) { - for (; p != e; ++p) { - IMMER_PREFETCH(p + 1); - make_full_leaf_pos(*p).visit(v, args...); - } - } else { - auto ss = shift_ - B; - for (; p != e; ++p) - make_full_pos(*p, ss).visit(v, args...); - } - } - - template <typename Visitor, typename... Args> - bool each_pred(Visitor v, Args&&... args) - { - auto p = node_->inner(); - auto e = p + branches<B>; - if (shift_ == BL) { - for (; p != e; ++p) { - IMMER_PREFETCH(p + 1); - if (!make_full_leaf_pos(*p).visit(v, args...)) - return false; - } - } else { - auto ss = shift_ - B; - for (; p != e; ++p) - if (!make_full_pos(*p, ss).visit(v, args...)) - return false; - } - return true; - } - - template <typename Visitor, typename... Args> - bool each_pred_zip(Visitor v, node_t* other, Args&&... args) - { - auto p = node_->inner(); - auto p2 = other->inner(); - auto e = p + branches<B>; - if (shift_ == BL) { - for (; p != e; ++p, ++p2) { - IMMER_PREFETCH(p + 1); - if (!make_full_leaf_pos(*p).visit(v, *p2, args...)) - return false; - } - } else { - auto ss = shift_ - B; - for (; p != e; ++p, ++p2) - if (!make_full_pos(*p, ss).visit(v, *p2, args...)) - return false; - } - return true; - } - - template <typename Visitor, typename... Args> - bool each_pred_i(Visitor v, count_t i, count_t n, Args&&... args) - { - auto p = node_->inner() + i; - auto e = node_->inner() + n; - if (shift_ == BL) { - for (; p != e; ++p) { - IMMER_PREFETCH(p + 1); - if (!make_full_leaf_pos(*p).visit(v, args...)) - return false; - } - } else { - auto ss = shift_ - B; - for (; p != e; ++p) - if (!make_full_pos(*p, ss).visit(v, args...)) - return false; - } - return true; - } - - template <typename Visitor, typename... Args> - void each_i(Visitor v, count_t i, count_t n, Args&&... args) - { - auto p = node_->inner() + i; - auto e = node_->inner() + n; - if (shift_ == BL) { - for (; p != e; ++p) { - IMMER_PREFETCH(p + 1); - make_full_leaf_pos(*p).visit(v, args...); - } - } else { - auto ss = shift_ - B; - for (; p != e; ++p) - make_full_pos(*p, ss).visit(v, args...); - } - } - - template <typename Visitor, typename... Args> - bool each_pred_right(Visitor v, count_t start, Args&&... args) - { - return each_pred_i(v, start, branches<B>, args...); - } - - template <typename Visitor, typename... Args> - bool each_pred_left(Visitor v, count_t last, Args&&... args) - { - return each_pred_i(v, 0, last, args...); - } - - template <typename Visitor, typename... Args> - void each_sub(Visitor v, Args&&... args) - { - each(v, args...); - } - - template <typename Visitor, typename... Args> - void each_left_sub(Visitor v, Args&&... args) - { - each_i(v, 0, branches<B> - 1, args...); - } - - template <typename Visitor, typename... Args> - void each_right_sub(Visitor v, Args&&... args) - { - each_i(v, 1, branches<B>, args...); - } - - template <typename Visitor, typename... Args> - void each_right(Visitor v, count_t start, Args&&... args) - { - each_i(v, start, branches<B>, args...); - } - - template <typename Visitor, typename... Args> - void each_left(Visitor v, count_t last, Args&&... args) - { - each_i(v, 0, last, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) towards(Visitor v, size_t idx, Args&&... args) - { - return towards_oh(v, idx, index(idx), args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) towards_oh_ch( - Visitor v, size_t idx, count_t offset_hint, count_t, Args&&... args) - { - return towards_oh(v, idx, offset_hint, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) - towards_oh(Visitor v, size_t idx, count_t offset_hint, Args&&... args) - { - assert(offset_hint == index(idx)); - auto is_leaf = shift_ == BL; - auto child = node_->inner()[offset_hint]; - return is_leaf - ? make_full_leaf_pos(child).visit(v, idx, args...) - : make_full_pos(child, shift_ - B).visit(v, idx, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) - towards_sub_oh(Visitor v, size_t idx, count_t offset_hint, Args&&... args) - { - assert(offset_hint == index(idx)); - auto is_leaf = shift_ == BL; - auto child = node_->inner()[offset_hint]; - auto lsize = offset_hint << shift_; - return is_leaf - ? make_full_leaf_pos(child).visit(v, idx - lsize, args...) - : make_full_pos(child, shift_ - B) - .visit(v, idx - lsize, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) first_sub(Visitor v, Args&&... args) - { - auto is_leaf = shift_ == BL; - auto child = node_->inner()[0]; - return is_leaf ? make_full_leaf_pos(child).visit(v, args...) - : make_full_pos(child, shift_ - B).visit(v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) first_sub_leaf(Visitor v, Args&&... args) - { - assert(shift_ == BL); - auto child = node_->inner()[0]; - return make_full_leaf_pos(child).visit(v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) first_sub_inner(Visitor v, Args&&... args) - { - assert(shift_ >= BL); - auto child = node_->inner()[0]; - return make_full_pos(child, shift_ - B).visit(v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) nth_sub(count_t idx, Visitor v, Args&&... args) - { - assert(idx < count()); - auto is_leaf = shift_ == BL; - auto child = node_->inner()[idx]; - return is_leaf ? make_full_leaf_pos(child).visit(v, args...) - : make_full_pos(child, shift_ - B).visit(v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) nth_sub_leaf(count_t idx, Visitor v, Args&&... args) - { - assert(shift_ == BL); - assert(idx < count()); - auto child = node_->inner()[idx]; - return make_full_leaf_pos(child).visit(v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) visit(Visitor v, Args&&... args) - { - return Visitor::visit_regular(*this, std::forward<Args>(args)...); - } -}; - -template <typename NodeT> -full_pos<NodeT> make_full_pos(NodeT* node, shift_t shift) -{ - assert(node); - assert(shift >= NodeT::bits_leaf); - return {node, shift}; -} - -template <typename NodeT> -struct relaxed_pos -{ - static constexpr auto B = NodeT::bits; - static constexpr auto BL = NodeT::bits_leaf; - - using node_t = NodeT; - using relaxed_t = typename NodeT::relaxed_t; - node_t* node_; - shift_t shift_; - relaxed_t* relaxed_; - - count_t count() const { return relaxed_->d.count; } - node_t* node() const { return node_; } - size_t size() const { return relaxed_->d.sizes[relaxed_->d.count - 1]; } - shift_t shift() const { return shift_; } - count_t subindex(size_t idx) const { return index(idx); } - relaxed_t* relaxed() const { return relaxed_; } - - size_t size_before(count_t offset) const - { - return offset ? relaxed_->d.sizes[offset - 1] : 0; - } - - size_t size(count_t offset) const - { - return size_sbh(offset, size_before(offset)); - } - - size_t size_sbh(count_t offset, size_t size_before_hint) const - { - assert(size_before_hint == size_before(offset)); - return relaxed_->d.sizes[offset] - size_before_hint; - } - - count_t index(size_t idx) const - { - auto offset = idx >> shift_; - while (relaxed_->d.sizes[offset] <= idx) - ++offset; - return offset; - } - - void copy_sizes(count_t offset, count_t n, size_t init, size_t* sizes) - { - auto e = sizes + n; - auto prev = size_before(offset); - auto these = relaxed_->d.sizes + offset; - for (; sizes != e; ++sizes, ++these) { - auto this_size = *these; - init = *sizes = init + (this_size - prev); - prev = this_size; - } - } - - template <typename Visitor, typename... Args> - void each(Visitor v, Args&&... args) - { - each_left(v, relaxed_->d.count, args...); - } - - template <typename Visitor, typename... Args> - bool each_pred(Visitor v, Args&&... args) - { - auto p = node_->inner(); - auto s = size_t{}; - auto n = count(); - if (shift_ == BL) { - for (auto i = count_t{0}; i < n; ++i) { - IMMER_PREFETCH(p + i + 1); - if (!make_leaf_sub_pos(p[i], relaxed_->d.sizes[i] - s) - .visit(v, args...)) - return false; - s = relaxed_->d.sizes[i]; - } - } else { - auto ss = shift_ - B; - for (auto i = count_t{0}; i < n; ++i) { - if (!visit_maybe_relaxed_sub( - p[i], ss, relaxed_->d.sizes[i] - s, v, args...)) - return false; - s = relaxed_->d.sizes[i]; - } - } - return true; - } - - template <typename Visitor, typename... Args> - bool each_pred_i(Visitor v, count_t i, count_t n, Args&&... args) - { - if (shift_ == BL) { - auto p = node_->inner(); - auto s = i > 0 ? relaxed_->d.sizes[i - 1] : 0; - for (; i < n; ++i) { - IMMER_PREFETCH(p + i + 1); - if (!make_leaf_sub_pos(p[i], relaxed_->d.sizes[i] - s) - .visit(v, args...)) - return false; - s = relaxed_->d.sizes[i]; - } - } else { - auto p = node_->inner(); - auto s = i > 0 ? relaxed_->d.sizes[i - 1] : 0; - auto ss = shift_ - B; - for (; i < n; ++i) { - if (!visit_maybe_relaxed_sub( - p[i], ss, relaxed_->d.sizes[i] - s, v, args...)) - return false; - s = relaxed_->d.sizes[i]; - } - } - return true; - } - - template <typename Visitor, typename... Args> - bool each_pred_left(Visitor v, count_t n, Args&&... args) - { - auto p = node_->inner(); - auto s = size_t{}; - if (shift_ == BL) { - for (auto i = count_t{0}; i < n; ++i) { - IMMER_PREFETCH(p + i + 1); - if (!make_leaf_sub_pos(p[i], relaxed_->d.sizes[i] - s) - .visit(v, args...)) - return false; - s = relaxed_->d.sizes[i]; - } - } else { - auto ss = shift_ - B; - for (auto i = count_t{0}; i < n; ++i) { - if (!visit_maybe_relaxed_sub( - p[i], ss, relaxed_->d.sizes[i] - s, v, args...)) - return false; - s = relaxed_->d.sizes[i]; - } - } - return true; - } - - template <typename Visitor, typename... Args> - bool each_pred_right(Visitor v, count_t start, Args&&... args) - { - assert(start > 0); - assert(start <= relaxed_->d.count); - auto s = relaxed_->d.sizes[start - 1]; - auto p = node_->inner(); - if (shift_ == BL) { - for (auto i = start; i < relaxed_->d.count; ++i) { - IMMER_PREFETCH(p + i + 1); - if (!make_leaf_sub_pos(p[i], relaxed_->d.sizes[i] - s) - .visit(v, args...)) - return false; - s = relaxed_->d.sizes[i]; - } - } else { - auto ss = shift_ - B; - for (auto i = start; i < relaxed_->d.count; ++i) { - if (!visit_maybe_relaxed_sub( - p[i], ss, relaxed_->d.sizes[i] - s, v, args...)) - return false; - s = relaxed_->d.sizes[i]; - } - } - return true; - } - - template <typename Visitor, typename... Args> - void each_i(Visitor v, count_t i, count_t n, Args&&... args) - { - if (shift_ == BL) { - auto p = node_->inner(); - auto s = i > 0 ? relaxed_->d.sizes[i - 1] : 0; - for (; i < n; ++i) { - IMMER_PREFETCH(p + i + 1); - make_leaf_sub_pos(p[i], relaxed_->d.sizes[i] - s) - .visit(v, args...); - s = relaxed_->d.sizes[i]; - } - } else { - auto p = node_->inner(); - auto s = i > 0 ? relaxed_->d.sizes[i - 1] : 0; - auto ss = shift_ - B; - for (; i < n; ++i) { - visit_maybe_relaxed_sub( - p[i], ss, relaxed_->d.sizes[i] - s, v, args...); - s = relaxed_->d.sizes[i]; - } - } - } - - template <typename Visitor, typename... Args> - void each_sub(Visitor v, Args&&... args) - { - each_left(v, relaxed_->d.count, args...); - } - - template <typename Visitor, typename... Args> - void each_left_sub(Visitor v, Args&&... args) - { - each_left(v, relaxed_->d.count - 1, args...); - } - - template <typename Visitor, typename... Args> - void each_left(Visitor v, count_t n, Args&&... args) - { - auto p = node_->inner(); - auto s = size_t{}; - if (shift_ == BL) { - for (auto i = count_t{0}; i < n; ++i) { - IMMER_PREFETCH(p + i + 1); - make_leaf_sub_pos(p[i], relaxed_->d.sizes[i] - s) - .visit(v, args...); - s = relaxed_->d.sizes[i]; - } - } else { - auto ss = shift_ - B; - for (auto i = count_t{0}; i < n; ++i) { - visit_maybe_relaxed_sub( - p[i], ss, relaxed_->d.sizes[i] - s, v, args...); - s = relaxed_->d.sizes[i]; - } - } - } - - template <typename Visitor, typename... Args> - void each_right_sub(Visitor v, Args&&... args) - { - each_right(v, 1, std::forward<Args>(args)...); - } - - template <typename Visitor, typename... Args> - void each_right(Visitor v, count_t start, Args&&... args) - { - assert(start > 0); - assert(start <= relaxed_->d.count); - auto s = relaxed_->d.sizes[start - 1]; - auto p = node_->inner(); - if (shift_ == BL) { - for (auto i = start; i < relaxed_->d.count; ++i) { - IMMER_PREFETCH(p + i + 1); - make_leaf_sub_pos(p[i], relaxed_->d.sizes[i] - s) - .visit(v, args...); - s = relaxed_->d.sizes[i]; - } - } else { - auto ss = shift_ - B; - for (auto i = start; i < relaxed_->d.count; ++i) { - visit_maybe_relaxed_sub( - p[i], ss, relaxed_->d.sizes[i] - s, v, args...); - s = relaxed_->d.sizes[i]; - } - } - } - - template <typename Visitor, typename... Args> - decltype(auto) towards(Visitor v, size_t idx, Args&&... args) - { - return towards_oh(v, idx, subindex(idx), args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) - towards_oh(Visitor v, size_t idx, count_t offset_hint, Args&&... args) - { - assert(offset_hint == index(idx)); - auto left_size = offset_hint ? relaxed_->d.sizes[offset_hint - 1] : 0; - return towards_oh_sbh(v, idx, offset_hint, left_size, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) towards_oh_sbh(Visitor v, - size_t idx, - count_t offset_hint, - size_t left_size_hint, - Args&&... args) - { - return towards_sub_oh_sbh(v, idx, offset_hint, left_size_hint, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) - towards_sub_oh(Visitor v, size_t idx, count_t offset_hint, Args&&... args) - { - assert(offset_hint == index(idx)); - auto left_size = offset_hint ? relaxed_->d.sizes[offset_hint - 1] : 0; - return towards_sub_oh_sbh(v, idx, offset_hint, left_size, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) towards_sub_oh_sbh(Visitor v, - size_t idx, - count_t offset_hint, - size_t left_size_hint, - Args&&... args) - { - assert(offset_hint == index(idx)); - assert(left_size_hint == - (offset_hint ? relaxed_->d.sizes[offset_hint - 1] : 0)); - auto child = node_->inner()[offset_hint]; - auto is_leaf = shift_ == BL; - auto next_size = relaxed_->d.sizes[offset_hint] - left_size_hint; - auto next_idx = idx - left_size_hint; - return is_leaf - ? make_leaf_sub_pos(child, next_size) - .visit(v, next_idx, args...) - : visit_maybe_relaxed_sub( - child, shift_ - B, next_size, v, next_idx, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) last_oh_csh(Visitor v, - count_t offset_hint, - size_t child_size_hint, - Args&&... args) - { - assert(offset_hint == count() - 1); - assert(child_size_hint == size(offset_hint)); - auto child = node_->inner()[offset_hint]; - auto is_leaf = shift_ == BL; - return is_leaf - ? make_leaf_sub_pos(child, child_size_hint).visit(v, args...) - : visit_maybe_relaxed_sub( - child, shift_ - B, child_size_hint, v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) last_sub(Visitor v, Args&&... args) - { - auto offset = relaxed_->d.count - 1; - auto child = node_->inner()[offset]; - auto child_size = size(offset); - auto is_leaf = shift_ == BL; - return is_leaf ? make_leaf_sub_pos(child, child_size).visit(v, args...) - : visit_maybe_relaxed_sub( - child, shift_ - B, child_size, v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) first_sub(Visitor v, Args&&... args) - { - auto child = node_->inner()[0]; - auto child_size = relaxed_->d.sizes[0]; - auto is_leaf = shift_ == BL; - return is_leaf ? make_leaf_sub_pos(child, child_size).visit(v, args...) - : visit_maybe_relaxed_sub( - child, shift_ - B, child_size, v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) first_sub_leaf(Visitor v, Args&&... args) - { - assert(shift_ == BL); - auto child = node_->inner()[0]; - auto child_size = relaxed_->d.sizes[0]; - return make_leaf_sub_pos(child, child_size).visit(v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) first_sub_inner(Visitor v, Args&&... args) - { - assert(shift_ > BL); - auto child = node_->inner()[0]; - auto child_size = relaxed_->d.sizes[0]; - return visit_maybe_relaxed_sub( - child, shift_ - B, child_size, v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) nth_sub(count_t offset, Visitor v, Args&&... args) - { - auto child = node_->inner()[offset]; - auto child_size = size(offset); - auto is_leaf = shift_ == BL; - return is_leaf ? make_leaf_sub_pos(child, child_size).visit(v, args...) - : visit_maybe_relaxed_sub( - child, shift_ - B, child_size, v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) nth_sub_leaf(count_t offset, Visitor v, Args&&... args) - { - assert(shift_ == BL); - auto child = node_->inner()[offset]; - auto child_size = size(offset); - return make_leaf_sub_pos(child, child_size).visit(v, args...); - } - - template <typename Visitor, typename... Args> - decltype(auto) visit(Visitor v, Args&&... args) - { - return Visitor::visit_relaxed(*this, std::forward<Args>(args)...); - } -}; - -template <typename Pos> -using is_relaxed = std::is_same<relaxed_pos<typename std::decay_t<Pos>::node_t>, - std::decay_t<Pos>>; - -template <typename Pos> -constexpr auto is_relaxed_v = is_relaxed<Pos>::value; - -template <typename NodeT> -relaxed_pos<NodeT> -make_relaxed_pos(NodeT* node, shift_t shift, typename NodeT::relaxed_t* relaxed) -{ - assert(node); - assert(relaxed); - assert(shift >= NodeT::bits_leaf); - return {node, shift, relaxed}; -} - -template <typename NodeT, typename Visitor, typename... Args> -decltype(auto) visit_maybe_relaxed_sub( - NodeT* node, shift_t shift, size_t size, Visitor v, Args&&... args) -{ - assert(node); - auto relaxed = node->relaxed(); - if (relaxed) { - assert(size == relaxed->d.sizes[relaxed->d.count - 1]); - return make_relaxed_pos(node, shift, relaxed) - .visit(v, std::forward<Args>(args)...); - } else { - return make_regular_sub_pos(node, shift, size) - .visit(v, std::forward<Args>(args)...); - } -} - -template <typename NodeT, - shift_t Shift, - bits_t B = NodeT::bits, - bits_t BL = NodeT::bits_leaf> -struct relaxed_descent_pos -{ - static_assert(Shift > 0, "not leaf..."); - - using node_t = NodeT; - using relaxed_t = typename NodeT::relaxed_t; - node_t* node_; - relaxed_t* relaxed_; - - count_t count() const { return relaxed_->d.count; } - node_t* node() const { return node_; } - shift_t shift() const { return Shift; } - size_t size() const { return relaxed_->d.sizes[relaxed_->d.count - 1]; } - - count_t index(size_t idx) const - { - // make gcc happy -#if !defined(_MSC_VER) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wshift-count-overflow" -#endif - auto offset = idx >> Shift; -#if !defined(_MSC_VER) -#pragma GCC diagnostic pop -#endif - while (relaxed_->d.sizes[offset] <= idx) - ++offset; - return offset; - } - - template <typename Visitor> - decltype(auto) descend(Visitor v, size_t idx) - { - auto offset = index(idx); - auto child = node_->inner()[offset]; - auto left_size = offset ? relaxed_->d.sizes[offset - 1] : 0; - auto next_idx = idx - left_size; - auto r = child->relaxed(); - return r ? relaxed_descent_pos<NodeT, Shift - B>{child, r}.visit( - v, next_idx) - : regular_descent_pos<NodeT, Shift - B>{child}.visit(v, - next_idx); - } - - template <typename Visitor, typename... Args> - decltype(auto) visit(Visitor v, Args&&... args) - { - return Visitor::visit_relaxed(*this, std::forward<Args>(args)...); - } -}; - -template <typename NodeT, bits_t B, bits_t BL> -struct relaxed_descent_pos<NodeT, BL, B, BL> -{ - using node_t = NodeT; - using relaxed_t = typename NodeT::relaxed_t; - node_t* node_; - relaxed_t* relaxed_; - - count_t count() const { return relaxed_->d.count; } - node_t* node() const { return node_; } - shift_t shift() const { return BL; } - size_t size() const { return relaxed_->d.sizes[relaxed_->d.count - 1]; } - - count_t index(size_t idx) const - { - auto offset = (idx >> BL) & mask<B>; - while (relaxed_->d.sizes[offset] <= idx) - ++offset; - return offset; - } - - template <typename Visitor> - decltype(auto) descend(Visitor v, size_t idx) - { - auto offset = index(idx); - auto child = node_->inner()[offset]; - auto left_size = offset ? relaxed_->d.sizes[offset - 1] : 0; - auto next_idx = idx - left_size; - return leaf_descent_pos<NodeT>{child}.visit(v, next_idx); - } - - template <typename Visitor, typename... Args> - decltype(auto) visit(Visitor v, Args&&... args) - { - return Visitor::visit_relaxed(*this, std::forward<Args>(args)...); - } -}; - -template <typename NodeT, typename Visitor, typename... Args> -decltype(auto) -visit_maybe_relaxed_descent(NodeT* node, shift_t shift, Visitor v, size_t idx) -{ - constexpr auto B = NodeT::bits; - constexpr auto BL = NodeT::bits_leaf; - assert(node); - assert(shift >= BL); - auto r = node->relaxed(); - if (r) { - switch (shift) { - case BL + B * 0: - return relaxed_descent_pos<NodeT, BL + B * 0>{node, r}.visit(v, - idx); - case BL + B * 1: - return relaxed_descent_pos<NodeT, BL + B * 1>{node, r}.visit(v, - idx); - case BL + B * 2: - return relaxed_descent_pos<NodeT, BL + B * 2>{node, r}.visit(v, - idx); - case BL + B * 3: - return relaxed_descent_pos<NodeT, BL + B * 3>{node, r}.visit(v, - idx); - case BL + B * 4: - return relaxed_descent_pos<NodeT, BL + B * 4>{node, r}.visit(v, - idx); - case BL + B * 5: - return relaxed_descent_pos<NodeT, BL + B * 5>{node, r}.visit(v, - idx); -#if IMMER_DESCENT_DEEP - default: - for (auto level = shift; level != endshift<B, BL>; level -= B) { - auto r = node->relaxed(); - if (r) { - auto node_idx = (idx >> level) & mask<B>; - while (r->d.sizes[node_idx] <= idx) - ++node_idx; - if (node_idx) - idx -= r->d.sizes[node_idx - 1]; - node = node->inner()[node_idx]; - } else { - do { - node = node->inner()[(idx >> level) & mask<B>]; - } while ((level -= B) != endshift<B, BL>); - return make_leaf_descent_pos(node).visit(v, idx); - } - } - return make_leaf_descent_pos(node).visit(v, idx); -#endif // IMMER_DESCENT_DEEP - } - IMMER_UNREACHABLE; - } else { - return visit_regular_descent(node, shift, v, idx); - } -} - -} // namespace rbts -} // namespace detail -} // namespace immer |