71 PowerOfTwoPermutableSequence<T,
80 static_assert(!PermutedLeaves || Fanout == 16 || Fanout == 32 ||
81 Fanout == 64 || Fanout == 256);
83 std::conditional_t<Fanout == 16,
85 std::conditional_t<Fanout == 256,
88 using Tree = permutations::detail::SequenceTree<
91 LengthLayout::cumulative,
93 SequenceTreePolicy<ReservedNodes,
94 std::conditional_t<PermutedLeaves, LeafOrder, void>>>;
96 static_assert(!CacheRegularPrefix || std::has_single_bit(Fanout));
100 RegularCache()
noexcept =
default;
101 RegularCache(RegularCache&& other) noexcept
102 : end(std::exchange(other.end, 0)) {}
103 RegularCache&
operator=(RegularCache&& other)
noexcept {
104 if (
this != &other) {
105 end = std::exchange(other.end, 0);
111 [[no_unique_address]]
112 std::conditional_t<CacheRegularPrefix, RegularCache, NoCache> regular_;
113 void refresh_regular()
noexcept {
114 if constexpr (CacheRegularPrefix) {
115 regular_.end = tree_.regular_prefix_size();
119 template <std::ranges::input_range Range>
121 constructible_from<T, std::ranges::range_rvalue_reference_t<Range>>
123 auto it = std::ranges::begin(range);
124 const auto end = std::ranges::end(range);
126 std::array<T, Values> values;
127 std::size_t count = 0;
128 while (count != Values && it != end) {
129 values[count++] = T(std::ranges::iter_move(it));
132 return Block(std::span<const T>(values.data(), count));
136 decltype(next)& read;
140 using difference_type [[maybe_unused]] = std::ptrdiff_t;
141 using iterator_concept [[maybe_unused]] = std::input_iterator_tag;
143 Block& operator*()
const noexcept {
return source->current; }
144 Iterator& operator++() {
145 source->current = source->read();
148 void operator++(
int) { ++*
this; }
149 bool operator==(std::default_sentinel_t)
const noexcept {
150 return source->current.empty();
157 std::default_sentinel_t end()
const noexcept {
return {}; }
160 result.tree_ = Tree::from_blocks(blocks);
161 result.refresh_regular();
165 std::size_t size_impl()
const noexcept {
return tree_.size(); }
166 T value_at_impl(std::size_t i)
const {
167 if constexpr (CacheRegularPrefix) {
168 if (i < regular_.end) {
169 return tree_.read_regular_unchecked(i);
174 void insert_at_impl(std::size_t position, T value) {
178 void rotate_left_impl(std::size_t left,
180 std::size_t distance) {
181 tree_.rotate_left(left, right, distance);
185 tree_.merge(donor.tree_);
187 donor.refresh_regular();
189 std::size_t memory_usage_bytes_impl()
const noexcept {
196 CacheRegularPrefix ?
sizeof(std::size_t) : 0;
221 auto result = tree_.memory_usage();
222 const auto extra =
sizeof(*this) -
sizeof(Tree);
223 result.total_bytes += std::min(extra, SIZE_MAX - result.total_bytes);
227#ifdef PIXIE_SEQUENCE_TREE_TESTING
230 using test_tree_type = Tree;
233 const Tree& test_tree() const noexcept {
return tree_; }