orx_split_vec/growth/recursive/
recursive_growth.rs1use crate::{Doubling, Fragment, Growth, SplitVec};
2use alloc::string::String;
3use orx_pseudo_default::PseudoDefault;
4
5#[derive(Debug, Default, Clone, PartialEq)]
44pub struct Recursive;
45
46impl PseudoDefault for Recursive {
47 fn pseudo_default() -> Self {
48 Default::default()
49 }
50}
51
52impl Growth for Recursive {
53 #[inline(always)]
54 fn new_fragment_capacity_from(
55 &self,
56 fragment_capacities: impl ExactSizeIterator<Item = usize>,
57 ) -> usize {
58 Doubling.new_fragment_capacity_from(fragment_capacities)
59 }
60
61 fn maximum_concurrent_capacity<T>(
62 &self,
63 fragments: &[Fragment<T>],
64 fragments_capacity: usize,
65 ) -> usize {
66 assert!(fragments_capacity >= fragments.len());
67
68 let current_capacity = fragments.iter().map(|x| x.capacity()).sum();
69 let mut last_capacity = fragments.last().map(|x| x.capacity()).unwrap_or(2);
70
71 let mut total_capacity = current_capacity;
72
73 for _ in fragments.len()..fragments_capacity {
74 last_capacity *= 2;
75 total_capacity += last_capacity;
76 }
77
78 total_capacity
79 }
80
81 fn required_fragments_len<T>(
82 &self,
83 fragments: &[Fragment<T>],
84 maximum_capacity: usize,
85 ) -> Result<usize, String> {
86 fn overflown_err() -> String {
87 alloc::format!(
88 "Maximum cumulative capacity that can be reached by the Recursive strategy is {}.",
89 usize::MAX
90 )
91 }
92
93 let current_capacity: usize = fragments.iter().map(|x| x.capacity()).sum();
94 let mut last_capacity = fragments.last().map(|x| x.capacity()).unwrap_or(2);
95
96 let mut total_capacity = current_capacity;
97 let mut f = fragments.len();
98
99 while total_capacity < maximum_capacity {
100 let (new_last_capacity, overflown) = last_capacity.overflowing_mul(2);
101 if overflown {
102 return Err(overflown_err());
103 }
104 last_capacity = new_last_capacity;
105
106 let (new_total_capacity, overflown) = total_capacity.overflowing_add(last_capacity);
107 if overflown {
108 return Err(overflown_err());
109 }
110
111 total_capacity = new_total_capacity;
112 f += 1;
113 }
114
115 Ok(f)
116 }
117
118 fn maximum_concurrent_capacity_bound<T>(
119 &self,
120 fragments: &[Fragment<T>],
121 fragments_capacity: usize,
122 ) -> usize {
123 Doubling.maximum_concurrent_capacity_bound(fragments, fragments_capacity)
124 }
125}
126
127impl<T> SplitVec<T, Recursive> {
128 pub fn with_recursive_growth() -> Self {
200 SplitVec::with_doubling_growth().into()
201 }
202
203 pub fn with_recursive_growth_and_fragments_capacity(fragments_capacity: usize) -> Self {
215 SplitVec::with_doubling_growth_and_fragments_capacity(fragments_capacity).into()
216 }
217
218 pub fn with_recursive_growth_and_max_concurrent_capacity() -> Self {
224 SplitVec::with_doubling_growth_and_max_concurrent_capacity().into()
225 }
226}
227
228#[cfg(test)]
229mod tests {
230 use super::*;
231 use crate::growth::doubling::constants::{CAPACITIES_LEN, FIRST_FRAGMENT_CAPACITY};
232 use alloc::vec::Vec;
233 use orx_pinned_vec::PinnedVec;
234
235 #[test]
236 fn get_fragment_and_inner_indices() {
237 let growth = Recursive;
238
239 let vecs = alloc::vec![
240 alloc::vec![0, 1, 2, 3],
241 alloc::vec![4, 5],
242 alloc::vec![6, 7, 8],
243 alloc::vec![9],
244 alloc::vec![10, 11, 12, 13, 14],
245 ];
246 let mut fragments: Vec<Fragment<_>> = vecs
247 .clone()
248 .into_iter()
249 .map(|x| Fragment::new(x.capacity(), x))
250 .collect();
251 let len = fragments.iter().map(|x| x.len()).sum();
252
253 let mut index = 0;
254 for (f, vec) in vecs.iter().enumerate() {
255 for (i, _) in vec.iter().enumerate() {
256 let maybe_fi = growth.get_fragment_and_inner_indices(len, &fragments, index);
257 assert_eq!(maybe_fi, Some((f, i)));
258
259 let ptr = growth.get_ptr_mut(&mut fragments, index).expect("is-some");
260 assert_eq!(unsafe { *ptr }, index);
261
262 unsafe { *ptr = 10 * index };
263 assert_eq!(unsafe { *ptr }, 10 * index);
264
265 index += 1;
266 }
267 }
268 }
269
270 #[test]
271 fn get_fragment_and_inner_indices_exhaustive() {
272 let growth = Recursive;
273
274 let mut fragments: Vec<Fragment<_>> = alloc::vec![];
275
276 #[cfg(not(miri))]
277 let lengths = [30, 1, 7, 3, 79, 147, 530];
278 #[cfg(miri)]
279 let lengths = [1, 7, 3, 30];
280
281 let mut index = 0;
282 for _ in 0..10 {
283 for &len in &lengths {
284 let mut vec = Vec::with_capacity(len);
285 for _ in 0..len {
286 vec.push(index);
287 index += 1;
288 }
289 let fragment = Fragment::new(len, vec);
290 fragments.push(fragment);
291 }
292 }
293
294 let total_len = fragments.iter().map(|x| x.len()).sum();
295
296 let mut index = 0;
297 let mut f = 0;
298 for _ in 0..10 {
299 for &len in &lengths {
300 for i in 0..len {
301 let maybe_fi =
302 growth.get_fragment_and_inner_indices(total_len, &fragments, index);
303
304 assert_eq!(maybe_fi, Some((f, i)));
305
306 let ptr = growth.get_ptr_mut(&mut fragments, index).expect("is-some");
307 assert_eq!(unsafe { *ptr }, index);
308
309 unsafe { *ptr = 10 * index };
310 assert_eq!(unsafe { *ptr }, 10 * index);
311
312 index += 1;
313 }
314 f += 1;
315 }
316 }
317 }
318
319 #[test]
320 fn maximum_concurrent_capacity() {
321 fn max_cap<T>(vec: &SplitVec<T, Recursive>) -> usize {
322 vec.growth()
323 .maximum_concurrent_capacity(vec.fragments(), vec.fragments.capacity())
324 }
325
326 let mut vec: SplitVec<char, Recursive> = SplitVec::with_recursive_growth();
327 assert_eq!(max_cap(&vec), 4 + 8 + 16 + 32);
328
329 let until = max_cap(&vec);
330 for _ in 0..until {
331 vec.push('x');
332 assert_eq!(max_cap(&vec), 4 + 8 + 16 + 32);
333 }
334
335 vec.push('x');
337 assert_eq!(max_cap(&vec), 4 + 8 + 16 + 32 + 64 + 128 + 256 + 512);
338 }
339
340 #[test]
341 fn maximum_concurrent_capacity_when_appended() {
342 fn max_cap<T>(vec: &SplitVec<T, Recursive>) -> usize {
343 vec.growth()
344 .maximum_concurrent_capacity(vec.fragments(), vec.fragments.capacity())
345 }
346
347 let mut vec: SplitVec<char, Recursive> = SplitVec::with_recursive_growth();
348 assert_eq!(max_cap(&vec), 4 + 8 + 16 + 32);
349
350 vec.append(alloc::vec!['x'; 10]);
351 assert_eq!(vec.fragments().len(), 2);
352 assert_eq!(vec.fragments()[1].capacity(), 10);
353 assert_eq!(vec.fragments()[1].len(), 10);
354
355 assert_eq!(max_cap(&vec), 4 + 10 + 20 + 40);
356 }
357
358 #[test]
359 fn with_recursive_growth_and_fragments_capacity_normal_growth() {
360 let mut vec: SplitVec<char, _> = SplitVec::with_recursive_growth_and_fragments_capacity(1);
361
362 assert_eq!(1, vec.fragments.capacity());
363
364 #[cfg(not(miri))]
365 let n = 100_000;
366 #[cfg(miri)]
367 let n = 55;
368
369 for _ in 0..n {
370 vec.push('x');
371 }
372
373 #[cfg(not(miri))]
374 assert!(vec.fragments.capacity() > 4);
375 }
376
377 #[test]
378 #[should_panic]
379 fn with_recursive_growth_and_fragments_capacity_zero() {
380 let _: SplitVec<char, _> = SplitVec::with_recursive_growth_and_fragments_capacity(0);
381 }
382
383 #[test]
384 #[should_panic]
385 fn with_recursive_growth_and_fragments_capacity_too_large_fragments_capacity() {
386 let vec: SplitVec<char, _> = SplitVec::with_recursive_growth_and_fragments_capacity(1000);
387 assert_eq!(
388 vec.maximum_concurrent_capacity(),
389 (1 << (CAPACITIES_LEN + 2)) - FIRST_FRAGMENT_CAPACITY
390 );
391 }
392
393 #[test]
394 fn with_recursive_growth_and_max_concurrent_capacity() {
395 let vec: SplitVec<char, _> = SplitVec::with_recursive_growth_and_max_concurrent_capacity();
396 assert_eq!(
397 vec.maximum_concurrent_capacity(),
398 (1 << (CAPACITIES_LEN + 2)) - FIRST_FRAGMENT_CAPACITY
399 );
400 }
401
402 #[test]
403 fn required_fragments_len() {
404 let vec: SplitVec<char, Recursive> = SplitVec::with_recursive_growth();
405 let num_fragments = |max_cap| {
406 vec.growth()
407 .required_fragments_len(vec.fragments(), max_cap)
408 };
409
410 assert_eq!(num_fragments(0), Ok(1));
412 assert_eq!(num_fragments(1), Ok(1));
413 assert_eq!(num_fragments(4), Ok(1));
414 assert_eq!(num_fragments(5), Ok(2));
415 assert_eq!(num_fragments(12), Ok(2));
416 assert_eq!(num_fragments(13), Ok(3));
417 assert_eq!(num_fragments(36), Ok(4));
418 assert_eq!(num_fragments(67), Ok(5));
419 assert_eq!(num_fragments(136), Ok(6));
420 }
421
422 #[test]
423 fn required_fragments_len_when_appended() {
424 let mut vec: SplitVec<char, Recursive> = SplitVec::with_recursive_growth();
425 for _ in 0..4 {
426 vec.push('x')
427 }
428 vec.append(alloc::vec!['x'; 10]);
429
430 let num_fragments = |max_cap| {
431 vec.growth()
432 .required_fragments_len(vec.fragments(), max_cap)
433 };
434
435 assert_eq!(num_fragments(0), Ok(2));
438 assert_eq!(num_fragments(1), Ok(2));
439 assert_eq!(num_fragments(14), Ok(2));
440 assert_eq!(num_fragments(15), Ok(3));
441 assert_eq!(num_fragments(21), Ok(3));
442 assert_eq!(num_fragments(34), Ok(3));
443 assert_eq!(num_fragments(35), Ok(4));
444 assert_eq!(num_fragments(74), Ok(4));
445 assert_eq!(num_fragments(75), Ok(5));
446 assert_eq!(num_fragments(154), Ok(5));
447 assert_eq!(num_fragments(155), Ok(6));
448 }
449}