38template<
typename T,
int64_t CapacityStart = 32,
int64_t CapacityMax = 4096>
class VectorList {
42 static_assert(is_power_of_2(CapacityStart));
43 static_assert(is_power_of_2(CapacityMax));
44 static_assert(CapacityStart <= CapacityMax);
56 this->append_vector();
62 vectors_ = std::move(other.vectors_);
63 used_vectors_ = other.used_vectors_;
65 other.clear_and_shrink();
86 template<
typename ForwardT>
void append_as(ForwardT &&value)
88 VectorT &
vector = this->ensure_space_for_one();
89 vector.append_unchecked_as(std::forward<ForwardT>(value));
100 return vectors_.first().first();
110 return vectors_[used_vectors_ - 1].last();
132 for (VectorT &
vector : vectors_) {
143 this->append_vector();
154 std::pair<int64_t, int64_t> index_pair = this->global_index_to_index_pair(index);
155 return vectors_[index_pair.first][index_pair.second];
164 std::pair<int64_t, int64_t> index_pair = this->global_index_to_index_pair(index);
165 return vectors_[index_pair.first][index_pair.second];
174 std::pair<int64_t, int64_t> global_index_to_index_pair(
int64_t index)
const
183 return CapacityStart * ((2 << index) - 1);
186 return log2((
sum / CapacityStart) + 1);
189 static const int64_t start_log2 =
log2(CapacityStart);
192 static const int64_t geometric_steps = end_log2 - start_log2 + 1;
194 static const int64_t geometric_total = geometric_sum(geometric_steps - 1);
197 if (index < geometric_total) {
198 index_a = index_from_sum(index);
199 index_b = index_a > 0 ? index - geometric_sum(index_a - 1) : index;
202 int64_t linear_start = index - geometric_total;
203 index_a = geometric_steps + linear_start / CapacityMax;
204 index_b = linear_start % CapacityMax;
206 return {index_a, index_b};
209 VectorT &ensure_space_for_one()
211 if (vectors_[used_vectors_ - 1].is_at_capacity()) {
212 if (used_vectors_ == vectors_.size()) {
213 this->append_vector();
217 return vectors_[used_vectors_ - 1];
222 const int64_t new_vector_capacity = this->get_next_vector_capacity();
224 vectors_.last().reserve(new_vector_capacity);
227 int64_t get_next_vector_capacity()
229 if (vectors_.is_empty()) {
230 return CapacityStart;
232 return std::min(vectors_.last().capacity() * 2, CapacityMax);
235 template<
typename IterableT,
typename ElemT>
struct Iterator {
236 IterableT &vector_list;
240 Iterator(IterableT &vector_list,
int64_t index_a = 0,
int64_t index_b = 0)
241 : vector_list(vector_list), index_a(index_a), index_b(index_b)
245 ElemT &operator*()
const
247 return vector_list.vectors_[index_a][index_b];
250 Iterator &operator++()
252 if (vector_list.vectors_[index_a].size() == index_b + 1) {
253 if (index_a + 1 == vector_list.used_vectors_) {
268 bool operator==(
const Iterator &other)
const
270 BLI_assert(&other.vector_list == &vector_list);
271 return other.index_a == index_a && other.index_b == index_b;
274 bool operator!=(
const Iterator &other)
const
276 return !(other == *
this);
280 using MutIterator = Iterator<SelfT, T>;
281 using ConstIterator = Iterator<const SelfT, const T>;
286 return MutIterator(*
this, 0, 0);
290 return MutIterator(*
this, used_vectors_ - 1, vectors_[used_vectors_ - 1].
size());
295 return ConstIterator(*
this, 0, 0);
299 return ConstIterator(*
this, used_vectors_ - 1, vectors_[used_vectors_ - 1].
size());
static T sum(const btAlignedObjectArray< T > &items)