Pixie
Loading...
Searching...
No Matches
permutation.h
1#pragma once
2
3#include <pixie/permutation.h>
4#include <pixie/permutations/detail/packed_value_block.h>
5#include <pixie/permutations/detail/sequence_tree.h>
6
7#include <algorithm>
8#include <array>
9#include <cstddef>
10#include <cstdint>
11#include <limits>
12#include <ranges>
13#include <span>
14#include <stdexcept>
15#include <type_traits>
16
17namespace pixie {
18
39template <class Index = std::uint64_t,
40 std::size_t StorageBits = 2048,
41 std::size_t Fanout = 8,
42 LengthLayout Layout = LengthLayout::cumulative>
44 : public PermutationBase<Permutation<Index, StorageBits, Fanout, Layout>,
45 Index> {
46 friend class PermutationBase<Permutation, Index>;
47 using block_type = permutations::detail::PackedValueBlock<Index, StorageBits>;
48 using tree_type =
49 permutations::detail::SequenceTree<block_type, Fanout, Layout, true>;
50 static_assert(std::is_integral_v<Index> && std::is_unsigned_v<Index> &&
51 !std::is_same_v<Index, bool> &&
52 std::numeric_limits<Index>::digits <= 64);
53
54 public:
57 Permutation() noexcept = default;
59 Permutation(const Permutation&) = delete;
61 Permutation& operator=(const Permutation&) = delete;
67 Permutation(Permutation&& other) noexcept = default;
74 Permutation& operator=(Permutation&& other) noexcept = default;
75
76 // Stream identity blocks without a full temporary index vector.
87 template <class Pred>
88 std::size_t lower_bound(Pred pred) const {
89 return tree_.lower_bound(pred);
90 }
91
99 struct MemoryUsage {
101 std::size_t blocks = 0;
103 std::size_t nodes = 0;
105 std::size_t payload_capacity_bytes = 0;
107 std::size_t block_metadata_bytes = 0;
110 std::size_t ordering_tree_bytes = 0;
112 std::size_t tag_padding_bytes = 0;
115 std::size_t facade_bytes = sizeof(Permutation);
118 std::size_t total_bytes = sizeof(Permutation);
119 };
120
126 MemoryUsage memory_usage() const noexcept {
127 using Untagged =
128 permutations::detail::SequenceTree<block_type, Fanout, Layout>;
129 const auto tree = tree_.memory_usage();
130 MemoryUsage result;
131 result.blocks = tree.blocks;
132 result.nodes = tree.nodes;
133 result.payload_capacity_bytes = tree_type::saturated_multiply(
134 tree.blocks, block_type{}.payload_capacity_bytes());
135 result.block_metadata_bytes = tree_type::saturated_multiply(
136 tree.blocks, block_type{}.metadata_bytes());
137 result.ordering_tree_bytes =
138 tree_type::saturated_multiply(tree.nodes, Untagged::node_storage_bytes);
139 result.tag_padding_bytes = tree_type::saturated_add(
140 tree_type::saturated_multiply(
141 tree.blocks, tree_type::block_storage_bytes - sizeof(block_type)),
142 tree_type::saturated_multiply(
143 tree.nodes,
144 tree_type::node_storage_bytes - Untagged::node_storage_bytes));
145 result.total_bytes = tree_type::saturated_add(
146 sizeof(*this),
147 tree_type::saturated_add(tree.block_bytes, tree.node_bytes));
148 return result;
149 }
150#ifdef PIXIE_SEQUENCE_TREE_TESTING
157 const tree_type& test_tree() const noexcept { return tree_; }
158#endif
159
160 private:
161 static Permutation identity_impl(std::size_t n) {
162 check_domain(n);
163 const auto count =
164 n / block_type::capacity + (n % block_type::capacity != 0);
165 auto blocks =
166 std::views::iota(std::size_t{0}, count) |
167 std::views::transform([n](std::size_t block) {
168 std::array<Index, block_type::capacity> fields;
169 const auto start = block * block_type::capacity;
170 const auto length = std::min(block_type::capacity, n - start);
171 for (std::size_t i = 0; i < length; ++i) {
172 fields[i] = static_cast<Index>(start + i);
173 }
174 return block_type(std::span<const Index>(fields.data(), length));
175 });
176 Permutation result;
177 result.tree_ = tree_type::from_blocks(blocks);
178 return result;
179 }
180 std::size_t size_impl() const noexcept { return tree_.size(); }
181 Index value_at_impl(std::size_t position) const { return tree_[position]; }
193 void insert_at_impl(std::size_t position) {
194 if (position > tree_.size()) {
195 throw std::out_of_range("Permutation: insert position");
196 }
197 check_domain(tree_.size() + 1);
198 tree_.insert_at(position, static_cast<Index>(tree_.size()));
199 }
200 void rotate_left_impl(std::size_t left,
201 std::size_t right,
202 std::size_t distance) {
203 tree_.rotate_left(left, right, distance);
204 }
205 // Validate the resulting index domain before rebasing the donor.
206 void merge_impl(Permutation& donor) {
207 if (this == &donor || donor.empty()) {
208 return;
209 }
210 if (donor.size() > std::numeric_limits<std::size_t>::max() - this->size()) {
211 throw std::length_error("Permutation: concatenation size");
212 }
213 check_domain(this->size() + donor.size());
214 tree_.merge_rebased(donor.tree_);
215 }
216 std::size_t memory_usage_bytes_impl() const noexcept {
217 return memory_usage().total_bytes;
218 }
219 static void check_domain(std::size_t n) {
220 if (n != 0 && n - 1 > std::numeric_limits<Index>::max()) {
221 throw std::length_error("Permutation: index domain");
222 }
223 }
224 tree_type tree_;
225};
226
227} // namespace pixie
CRTP contract for exclusively owned permutations of [0,size()).
Definition permutation.h:41
MemoryUsage memory_usage() const noexcept
Explicit linear-time live allocation accounting.
Definition permutation.h:126
Permutation() noexcept=default
Construct empty.
std::size_t lower_bound(Pred pred) const
Definition permutation.h:88
Lightweight permutation CRTP contract.
LengthLayout
Representation of tree child lengths.
Definition sequence_options.h:14
Requested live storage breakdown, excluding allocator bookkeeping.
Definition permutation.h:99
std::size_t blocks
Leaf count.
Definition permutation.h:101
std::size_t ordering_tree_bytes
Untagged node bytes.
Definition permutation.h:110
std::size_t payload_capacity_bytes
Packed payload bytes.
Definition permutation.h:105
std::size_t total_bytes
Total live bytes.
Definition permutation.h:118
std::size_t nodes
Internal node count.
Definition permutation.h:103
std::size_t tag_padding_bytes
Incremental tag bytes.
Definition permutation.h:112
std::size_t block_metadata_bytes
Local bookkeeping bytes.
Definition permutation.h:107
std::size_t facade_bytes
Inline owner bytes.
Definition permutation.h:115