Pixie
Loading...
Searching...
No Matches
power_of_two_sequence.h
Go to the documentation of this file.
1#pragma once
2
11
13#include <pixie/experimental/power_of_two_value_block.h>
14#include <pixie/experimental/sequence_tree_policy.h>
18#include <pixie/permutations/detail/sequence_tree.h>
19
20#include <algorithm>
21#include <array>
22#include <bit>
23#include <concepts>
24#include <cstddef>
25#include <cstdint>
26#include <iterator>
27#include <ranges>
28#include <span>
29#include <type_traits>
30#include <utility>
31
32namespace pixie::experimental {
33
63template <class T = std::uint64_t,
64 std::size_t Values = 256,
65 std::size_t Fanout = 32,
66 std::size_t ReservedNodes = 0,
67 bool CacheRegularPrefix = false,
68 bool PermutedLeaves = false>
71 PowerOfTwoPermutableSequence<T,
72 Values,
73 Fanout,
74 ReservedNodes,
75 CacheRegularPrefix,
76 PermutedLeaves>,
77 T,
78 T> {
80 static_assert(!PermutedLeaves || Fanout == 16 || Fanout == 32 ||
81 Fanout == 64 || Fanout == 256);
82 using LeafOrder =
83 std::conditional_t<Fanout == 16,
85 std::conditional_t<Fanout == 256,
88 using Tree = permutations::detail::SequenceTree<
89 Block,
90 Fanout,
91 LengthLayout::cumulative,
92 false,
93 SequenceTreePolicy<ReservedNodes,
94 std::conditional_t<PermutedLeaves, LeafOrder, void>>>;
96 static_assert(!CacheRegularPrefix || std::has_single_bit(Fanout));
97 struct NoCache {};
98 struct RegularCache {
99 std::size_t end = 0;
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);
106 }
107 return *this;
108 }
109 };
110 Tree tree_;
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();
116 }
117 }
118
119 template <std::ranges::input_range Range>
120 requires std::
121 constructible_from<T, std::ranges::range_rvalue_reference_t<Range>>
122 static PowerOfTwoPermutableSequence from_range_impl(Range&& range) {
123 auto it = std::ranges::begin(range);
124 const auto end = std::ranges::end(range);
125 auto next = [&] {
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));
130 ++it;
131 }
132 return Block(std::span<const T>(values.data(), count));
133 };
134 // A consuming input cursor: dereferencing does not advance the source.
135 struct Blocks {
136 decltype(next)& read;
137 Block current;
138 struct Iterator {
139 using value_type [[maybe_unused]] = Block;
140 using difference_type [[maybe_unused]] = std::ptrdiff_t;
141 using iterator_concept [[maybe_unused]] = std::input_iterator_tag;
142 Blocks* source;
143 Block& operator*() const noexcept { return source->current; }
144 Iterator& operator++() {
145 source->current = source->read();
146 return *this;
147 }
148 void operator++(int) { ++*this; }
149 bool operator==(std::default_sentinel_t) const noexcept {
150 return source->current.empty();
151 }
152 };
153 Iterator begin() {
154 current = read();
155 return {this};
156 }
157 std::default_sentinel_t end() const noexcept { return {}; }
158 } blocks{next, {}};
160 result.tree_ = Tree::from_blocks(blocks);
161 result.refresh_regular();
162 return result;
163 }
164
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);
170 }
171 }
172 return tree_[i];
173 }
174 void insert_at_impl(std::size_t position, T value) {
175 tree_.insert_at(position, value);
176 refresh_regular();
177 }
178 void rotate_left_impl(std::size_t left,
179 std::size_t right,
180 std::size_t distance) {
181 tree_.rotate_left(left, right, distance);
182 refresh_regular();
183 }
184 void merge_impl(PowerOfTwoPermutableSequence& donor) {
185 tree_.merge(donor.tree_);
186 refresh_regular();
187 donor.refresh_regular();
188 }
189 std::size_t memory_usage_bytes_impl() const noexcept {
190 return memory_usage().total_bytes;
191 }
192
193 public:
195 static constexpr std::size_t regular_cache_bytes =
196 CacheRegularPrefix ? sizeof(std::size_t) : 0;
199 static constexpr ElementStorage storage = ElementStorage::packed;
201 PowerOfTwoPermutableSequence() noexcept = default;
206 delete;
209 default;
212 PowerOfTwoPermutableSequence&&) noexcept = default;
220 auto memory_usage() const noexcept {
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);
224 return result;
225 }
226
227#ifdef PIXIE_SEQUENCE_TREE_TESTING
230 using test_tree_type = Tree;
233 const Tree& test_tree() const noexcept { return tree_; }
234#endif
235};
236
237} // namespace pixie::experimental
CRTP contract for exclusively owned sequences with immutable reads.
Definition permutable_sequence.h:53
void insert_at(size_type position, T value)
Insert one value at a zero-based position.
Definition permutable_sequence.h:121
Byte-index control for the split-bit slot-order experiment.
Definition slot_order.h:282
Experimental ordering of 256 pointer slots in one 16x16 node.
Definition grouped_slot_order256.h:35
auto memory_usage() const noexcept
Account for this object and all live requested tree storage.
Definition power_of_two_sequence.h:220
static constexpr std::size_t regular_cache_bytes
Extra owner bytes used by the optional regular-prefix cache.
Definition power_of_two_sequence.h:195
PowerOfTwoPermutableSequence() noexcept=default
Construct canonical empty without allocating.
PowerOfTwoPermutableSequence & operator=(const PowerOfTwoPermutableSequence &)=delete
Exclusive owners cannot be copy-assigned.
static constexpr ElementStorage storage
Resolved storage strategy; elements are packed and read by value.
Definition power_of_two_sequence.h:199
Packed unsigned leaf with a power-of-two element capacity.
Definition power_of_two_value_block.h:33
Experimental logical ordering of sixteen stable physical slots.
Definition slot_order16.h:32
Single-node 16x16 child-order experiment.
Definition excess.h:90
Lightweight immutable-read permutable-sequence CRTP contract.
ElementStorage
Compile-time element storage selection.
Definition permutable_sequence.h:23
Packed ordering primitive for the intermediate-node experiment.
Experimental split-bit and byte orders for 32/64 physical slots.