Pixie
Loading...
Searching...
No Matches
slot_order16.h
Go to the documentation of this file.
1#pragma once
2
11
12#include <array>
13#include <bit>
14#include <cassert>
15#include <cstddef>
16#include <cstdint>
17
18namespace pixie::experimental {
19
33 public:
35 static constexpr std::size_t capacity = 16;
37 explicit SlotOrder16(std::size_t count = 0) noexcept
38 : order_(0xfedcba9876543210ULL & mask(unsigned(count * 4))),
39 occupied_(std::uint16_t(mask(unsigned(count)))),
40 count_(std::uint8_t(count)) {
41 assert(count <= 16);
42 }
43
45 std::size_t size() const noexcept { return count_; }
46
48 unsigned operator[](std::size_t index) const noexcept {
49 assert(index < size());
50 return unsigned((order_ >> (4 * index)) & 15);
51 }
52
54 std::uint16_t occupied() const noexcept { return occupied_; }
55
57 bool valid() const noexcept {
58 if (size() > capacity) {
59 return false;
60 }
61 unsigned seen = 0;
62 for (std::size_t i = 0; i < size(); ++i) {
63 const auto bit = 1u << (*this)[i];
64 if (seen & bit) {
65 return false;
66 }
67 seen |= bit;
68 }
69 return seen == occupied_;
70 }
71
77 std::size_t rotate_children(std::array<void*, capacity>&,
78 std::size_t left,
79 std::size_t right,
80 std::size_t distance) noexcept {
81 rotate_left(left, right, distance);
82 return 0;
83 }
84
89 void rotate_left(std::size_t left,
90 std::size_t right,
91 std::size_t distance) noexcept {
92 assert(left <= right && right <= size());
93 const auto length = right - left;
94 if (length == 0 || (distance %= length) == 0) {
95 return;
96 }
97 const auto bits = unsigned(4 * length);
98 const auto shift = unsigned(4 * left);
99 const auto region_mask = mask(bits);
100 const auto region = (order_ >> shift) & region_mask;
101 const auto rotated =
102 (region >> (4 * distance)) | (region << (4 * (length - distance)));
103 order_ =
104 (order_ & ~(region_mask << shift)) | ((rotated & region_mask) << shift);
105 }
106
113 unsigned insert(std::size_t position) noexcept {
114 assert(position <= size() && size() < 16);
115 const auto slot =
116 unsigned(std::countr_zero(unsigned(std::uint16_t(~occupied_))));
117 order_ |= std::uint64_t(slot) << (4 * count_);
118 occupied_ |= std::uint16_t(1u << slot);
119 ++count_;
120 rotate_left(position, size(), size() - position - 1);
121 return slot;
122 }
123
128 unsigned erase(std::size_t position) noexcept {
129 assert(position < size());
130 const auto slot = (*this)[position];
131 rotate_left(position, size(), 1);
132 --count_;
133 order_ &= mask(unsigned(4 * count_));
134 occupied_ &= std::uint16_t(~(1u << slot));
135 return slot;
136 }
137
138 private:
139 static constexpr std::uint64_t mask(unsigned bits) noexcept {
140 return bits >= 64 ? ~std::uint64_t{0} : (std::uint64_t{1} << bits) - 1;
141 }
142 std::uint64_t order_;
143 std::uint16_t occupied_;
144 std::uint8_t count_;
145};
146
147} // namespace pixie::experimental
bool valid() const noexcept
Check logical mapping uniqueness against physical occupancy.
Definition slot_order16.h:57
void rotate_left(std::size_t left, std::size_t right, std::size_t distance) noexcept
Rotate logical [left, right) left by distance modulo its length.
Definition slot_order16.h:89
static constexpr std::size_t capacity
Maximum occupied child count.
Definition slot_order16.h:35
unsigned erase(std::size_t position) noexcept
Remove a logical entry and return its now-free physical slot.
Definition slot_order16.h:128
unsigned operator[](std::size_t index) const noexcept
Physical slot for logical index; requires index < size().
Definition slot_order16.h:48
SlotOrder16(std::size_t count=0) noexcept
Construct empty, or identity order of count slots; count <= 16.
Definition slot_order16.h:37
unsigned insert(std::size_t position) noexcept
Insert a free slot at logical position and return its physical index.
Definition slot_order16.h:113
std::uint16_t occupied() const noexcept
Bit s is set exactly when physical slot s is occupied.
Definition slot_order16.h:54
std::size_t size() const noexcept
Number of occupied slots, in [0, 16].
Definition slot_order16.h:45
std::size_t rotate_children(std::array< void *, capacity > &, std::size_t left, std::size_t right, std::size_t distance) noexcept
Rotate logical [left,right) without moving any supplied pointers.
Definition slot_order16.h:77
Definition excess.h:90