44 using Policy = immer::memory_policy<HeapPolicy,
45 immer::default_refcount_policy,
46 immer::default_lock_policy>;
47 using Vector = immer::flex_vector<T, Policy>;
48 using Tree = std::remove_cvref_t<decltype(std::declval<Vector>().impl())>;
49 using Node =
typename Tree::node_t;
50 static_assert(Node::keep_headroom);
51 static_assert(
alignof(T) <=
alignof(std::max_align_t));
55 static constexpr std::size_t
fanout = std::size_t{1} << Vector::bits;
68 : values_(std::exchange(other.values_, Vector{})) {}
72 values_ = std::exchange(other.values_, Vector{});
102 if (!values_.empty()) {
103 const auto& tree = values_.impl();
104 const auto tail_offset = tree.tail_offset();
105 if (tail_offset != 0) {
106 count_tree(tree.root, tree.shift, tail_offset, result);
117 template <std::ranges::input_range Range>
119 constructible_from<T, std::ranges::range_rvalue_reference_t<Range>>
121 auto transient = Vector{}.transient();
122 auto it = std::ranges::begin(range);
123 const auto end = std::ranges::end(range);
124 for (; it != end; ++it) {
125 if (transient.size() == Vector::max_size()) {
126 throw std::length_error(
"ImmerPermutableSequence: size limit");
128 transient.push_back(T(std::ranges::iter_move(it)));
131 result.values_ = std::move(transient).persistent();
135 std::size_t size_impl() const noexcept {
return values_.size(); }
136 T value_at_impl(std::size_t position)
const {
137 if (position >= values_.size()) {
138 throw std::out_of_range(
"ImmerPermutableSequence: read position");
140 return values_[position];
142 void insert_at_impl(std::size_t position, T value) {
143 if (position > values_.size()) {
144 throw std::out_of_range(
"ImmerPermutableSequence: insert position");
148 values_ = values_.insert(position, std::move(value));
150 void rotate_left_impl(std::size_t left,
152 std::size_t distance) {
153 if (left > right || right > values_.size()) {
154 throw std::out_of_range(
"ImmerPermutableSequence: rotation range");
156 if (left == right || (distance %= right - left) == 0) {
159 auto prefix = values_.take(left);
160 auto first = values_.drop(left).take(distance);
161 auto second = values_.drop(left + distance).take(right - left - distance);
162 auto suffix = values_.drop(right);
163 auto result = std::move(prefix) + std::move(second) + std::move(first) +
165 values_ = std::move(result);
168 if (
this == &donor || donor.empty()) {
171 check_growth(donor.size());
173 *
this = std::move(donor);
176 auto result = values_ + donor.values_;
177 values_ = std::move(result);
178 donor.values_ = Vector{};
180 std::size_t memory_usage_bytes_impl() const noexcept {
183 void check_growth(std::size_t count)
const {
184 if (count > Vector::max_size() - values_.size()) {
185 throw std::length_error(
"ImmerPermutableSequence: size limit");
188 static void add(std::size_t& total, std::size_t bytes)
noexcept {
189 const auto maximum = std::numeric_limits<std::size_t>::max();
190 total = bytes > maximum - total ? maximum : total + bytes;
192 static void count_tree(Node* node,
196 if (shift < Vector::bits_leaf) {
198 add(result.block_bytes, Node::max_sizeof_leaf);
202 const auto* relaxed = node->relaxed();
203 add(result.node_bytes,
204 relaxed ? Node::max_sizeof_inner_r : Node::max_sizeof_inner);
205 if (relaxed && !Node::embed_relaxed) {
206 add(result.node_bytes, Node::max_sizeof_relaxed);
208 const auto child_capacity = std::size_t{1} << shift;
210 relaxed ? relaxed->d.count : 1 + (
size - 1) / child_capacity;
211 std::size_t prefix = 0;
212 for (std::size_t i = 0; i < count; ++i) {
213 const auto end = relaxed ? relaxed->d.sizes[i]
214 : std::min(
size, prefix + child_capacity);
215 if (shift == Vector::bits_leaf) {
217 add(result.block_bytes, Node::max_sizeof_leaf);
219 count_tree(node->inner()[i], shift - Vector::bits, end - prefix,