diff --git a/Cargo.toml b/Cargo.toml index 4b0c12f..fa9a029 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "orx-linked-list" -version = "4.0.0" +version = "4.1.0" edition = "2024" authors = ["orxfun "] description = "A linked list implementation with unique features and an extended list of constant time methods providing high performance traversals and mutations." @@ -16,7 +16,7 @@ orx-pinned-vec = { version = "3.21.0", default-features = false } orx-fixed-vec = { version = "3.22.0", default-features = false } orx-split-vec = { version = "3.22.0", default-features = false } orx-concurrent-iter = { version = "3.3.0", default-features = false } -orx-selfref-col = { version = "3.0.0", default-features = false } +orx-selfref-col = { version = "3.1.0", default-features = false } orx-parallel = { version = "3.4.0", default-features = false, optional = true } [dev-dependencies] diff --git a/examples/bench_parallelization.rs b/examples/bench_parallelization.rs index fbfcdba..931a927 100644 --- a/examples/bench_parallelization.rs +++ b/examples/bench_parallelization.rs @@ -33,25 +33,28 @@ fn main() { let args = Args::parse(); let expected_output = { - let list: DoublyList<_> = (0..args.len as usize).collect(); + let list: DoublyList<_> = (0..args.len).collect(); list.iter() .filter(|x| *x % 3 != 0) .map(|x| x + fibonacci(x % 1000)) - .filter_map(|x| (x % 2 == 0).then(|| x.to_string())) + .filter(|&x| x % 2 == 0) + .map(|x| x.to_string()) .collect::>() }; - let computations: Vec<(&str, Box Vec>)> = vec![ + type Compute = dyn Fn() -> Vec; + let computations: Vec<(&str, Box)> = vec![ ( "Sequential computation over std::collections::LinkedList", Box::new(move || { - let list: std::collections::LinkedList<_> = (0..args.len as usize).collect(); + let list: std::collections::LinkedList<_> = (0..args.len).collect(); list.iter() .filter(|x| *x % 3 != 0) .map(|x| x + fibonacci(x % 1000)) - .filter_map(|x| (x % 2 == 0).then(|| x.to_string())) + .filter(|&x| x % 2 == 0) + .map(|x| x.to_string()) .collect::>() }), ), @@ -59,12 +62,13 @@ fn main() { ( "Sequential computation over DoublyList", Box::new(move || { - let list: DoublyList<_> = (0..args.len as usize).collect(); + let list: DoublyList<_> = (0..args.len).collect(); list.iter_x() .filter(|x| *x % 3 != 0) .map(|x| x + fibonacci(x % 1000)) - .filter_map(|x| (x % 2 == 0).then(|| x.to_string())) + .filter(|&x| x % 2 == 0) + .map(|x| x.to_string()) .collect::>() }), ), @@ -72,7 +76,7 @@ fn main() { ( "Parallelized over DoublyList using orx_parallel", Box::new(move || { - let list: DoublyList<_> = (0..args.len as usize).collect(); + let list: DoublyList<_> = (0..args.len).collect(); list.par_x() // replace iter_x (into_iter_x) with par_x (into_par_x) to parallelize ! .filter(|x| *x % 3 != 0) diff --git a/examples/tour_mutations.rs b/examples/tour_mutations.rs index 1161cd2..5c4b417 100644 --- a/examples/tour_mutations.rs +++ b/examples/tour_mutations.rs @@ -2,7 +2,7 @@ use clap::Parser; use orx_linked_list::*; use rand::prelude::*; use rand_chacha::ChaCha8Rng; -use std::{fmt::Debug, time::Instant, usize}; +use std::{fmt::Debug, time::Instant}; fn get_cities(num_cities: usize) -> impl Iterator { (0..num_cities).map(|id| City { diff --git a/examples/utils/benchmark_utils.rs b/examples/utils/benchmark_utils.rs index 4ab3241..4f7f2ab 100644 --- a/examples/utils/benchmark_utils.rs +++ b/examples/utils/benchmark_utils.rs @@ -35,11 +35,13 @@ where now.elapsed().unwrap() } +type Compute = dyn Fn() -> O; + pub fn timed_reduce_all( benchmark_name: &str, num_repetitions: usize, expected_output: Option, - computations: &[(&str, Box O>)], + computations: &[(&str, Box>)], ) where O: PartialEq + Debug + Clone, { @@ -80,7 +82,7 @@ pub fn timed_collect_all( benchmark_name: &str, num_repetitions: usize, expected_output: &[O], - computations: &[(&str, Box Out>)], + computations: &[(&str, Box>)], ) where Out: IntoIterator, O: PartialEq + Debug, diff --git a/src/tests/doubly.rs b/src/tests/doubly.rs index 8786776..efbf358 100644 --- a/src/tests/doubly.rs +++ b/src/tests/doubly.rs @@ -51,22 +51,22 @@ where assert_ne!(self.0.ends().get(BACK_IDX), self.0.ends().get(FRONT_IDX)); let mut fwd_pointers = alloc::vec![]; - let mut ptr = self.0.ends().get(FRONT_IDX).cloned().unwrap(); - fwd_pointers.push(ptr.clone()); - while let Some((next_ptr, next)) = self.next(&ptr) { - assert_eq!(next.prev().get(), Some(&ptr)); + let mut ptr = self.0.ends().get(FRONT_IDX).unwrap(); + fwd_pointers.push(ptr); + while let Some((next_ptr, next)) = self.next(ptr) { + assert_eq!(next.prev().get(), Some(ptr)); ptr = next_ptr; - fwd_pointers.push(ptr.clone()); + fwd_pointers.push(ptr); } assert_eq!(fwd_pointers.len(), num_active_nodes); let mut bwd_pointers = alloc::vec![]; - let mut ptr = self.0.ends().get(BACK_IDX).cloned().unwrap(); - bwd_pointers.push(ptr.clone()); - while let Some((prev_ptr, prev)) = self.prev(&ptr) { - assert_eq!(prev.next().get(), Some(&ptr)); + let mut ptr = self.0.ends().get(BACK_IDX).unwrap(); + bwd_pointers.push(ptr); + while let Some((prev_ptr, prev)) = self.prev(ptr) { + assert_eq!(prev.next().get(), Some(ptr)); ptr = prev_ptr; - bwd_pointers.push(ptr.clone()); + bwd_pointers.push(ptr); } bwd_pointers.reverse(); @@ -79,14 +79,12 @@ where assert_eq!(iter.next(), self.front()); - let mut maybe_ptr = self.0.ends().get(FRONT_IDX).cloned(); + let mut maybe_ptr = self.0.ends().get(FRONT_IDX); for _ in 1..num_active_nodes { - let ptr = maybe_ptr.clone().unwrap(); - maybe_ptr = self.next(&ptr).map(|x| x.0); + let ptr = maybe_ptr.unwrap(); + maybe_ptr = self.next(ptr).map(|x| x.0); - let data = maybe_ptr - .clone() - .map(|p| unsafe { self.0.data_unchecked(&p) }); + let data = maybe_ptr.map(|p| unsafe { self.0.data_unchecked(p) }); assert_eq!(iter.next(), data); } assert!(iter.next().is_none()); @@ -96,14 +94,12 @@ where assert_eq!(iter.next(), self.back()); - let mut maybe_ptr = self.0.ends().get(BACK_IDX).cloned(); + let mut maybe_ptr = self.0.ends().get(BACK_IDX); for _ in 1..num_active_nodes { - let ptr = maybe_ptr.clone().unwrap(); - maybe_ptr = self.prev(&ptr).map(|x| x.0); + let ptr = maybe_ptr.unwrap(); + maybe_ptr = self.prev(ptr).map(|x| x.0); - let data = maybe_ptr - .clone() - .map(|p| unsafe { self.0.data_unchecked(&p) }); + let data = maybe_ptr.map(|p| unsafe { self.0.data_unchecked(p) }); assert_eq!(iter.next(), data); } assert!(iter.next().is_none()); diff --git a/src/tests/singly.rs b/src/tests/singly.rs index ddb49fd..f147dc0 100644 --- a/src/tests/singly.rs +++ b/src/tests/singly.rs @@ -39,11 +39,11 @@ where assert!(self.front().is_some()); let mut fwd_pointers = alloc::vec![]; - let mut ptr = self.0.ends().get().cloned().unwrap(); - fwd_pointers.push(ptr.clone()); - while let Some((next_ptr, _)) = self.next(&ptr) { + let mut ptr = self.0.ends().get().unwrap(); + fwd_pointers.push(ptr); + while let Some((next_ptr, _)) = self.next(ptr) { ptr = next_ptr; - fwd_pointers.push(ptr.clone()); + fwd_pointers.push(ptr); } assert_eq!(fwd_pointers.len(), num_active_nodes); } @@ -54,14 +54,12 @@ where assert_eq!(iter.next(), self.front()); - let mut maybe_ptr = self.0.ends().get().cloned(); + let mut maybe_ptr = self.0.ends().get(); for _ in 1..num_active_nodes { - let ptr = maybe_ptr.clone().unwrap(); - maybe_ptr = self.next(&ptr).map(|x| x.0); + let ptr = maybe_ptr.unwrap(); + maybe_ptr = self.next(ptr).map(|x| x.0); - let data = maybe_ptr - .clone() - .map(|p| unsafe { self.0.data_unchecked(&p) }); + let data = maybe_ptr.map(|p| unsafe { self.0.data_unchecked(p) }); assert_eq!(iter.next(), data); } assert!(iter.next().is_none()); diff --git a/src/variant.rs b/src/variant.rs index 5e72c69..c2f89ee 100644 --- a/src/variant.rs +++ b/src/variant.rs @@ -12,6 +12,11 @@ pub struct Singly { p: PhantomData, } +/// # SAFETY +/// +/// List variants do not hold any data, safe to send or sync. +unsafe impl Sync for Singly {} + impl Variant for Singly { type Item = T; @@ -32,6 +37,11 @@ pub struct Doubly { p: PhantomData, } +/// # SAFETY +/// +/// List variants do not hold any data, safe to send or sync. +unsafe impl Sync for Doubly {} + impl Variant for Doubly { type Item = T; diff --git a/tests/list_move_next_to.rs b/tests/list_move_next_to.rs index 159bfbb..25e6850 100644 --- a/tests/list_move_next_to.rs +++ b/tests/list_move_next_to.rs @@ -13,7 +13,7 @@ fn list_move_next_to_front() { let (mut list, idx) = list_and_indices(n); list.move_next_to(idx[i], idx[0]); - let mut vec: Vec<_> = (0..n).into_iter().filter(|x| x != &i).collect(); + let mut vec: Vec<_> = (0..n).filter(|x| x != &i).collect(); vec.insert(1, i); #[cfg(feature = "validation")] @@ -29,7 +29,7 @@ fn list_move_next_to_back() { let (mut list, idx) = list_and_indices(n); list.move_next_to(idx[i], idx[n - 1]); - let mut vec: Vec<_> = (0..n).into_iter().filter(|x| x != &i).collect(); + let mut vec: Vec<_> = (0..n).filter(|x| x != &i).collect(); vec.insert(n - 1, i); #[cfg(feature = "validation")] diff --git a/tests/list_move_prev_to.rs b/tests/list_move_prev_to.rs index de96e07..da13368 100644 --- a/tests/list_move_prev_to.rs +++ b/tests/list_move_prev_to.rs @@ -13,7 +13,7 @@ fn list_move_prev_to_front() { let (mut list, idx) = list_and_indices(n); list.move_prev_to(idx[i], idx[0]); - let mut vec: Vec<_> = (0..n).into_iter().filter(|x| x != &i).collect(); + let mut vec: Vec<_> = (0..n).filter(|x| x != &i).collect(); vec.insert(0, i); #[cfg(feature = "validation")] @@ -29,7 +29,7 @@ fn list_move_prev_to_back() { let (mut list, idx) = list_and_indices(n); list.move_prev_to(idx[i], idx[n - 1]); - let mut vec: Vec<_> = (0..n).into_iter().filter(|x| x != &i).collect(); + let mut vec: Vec<_> = (0..n).filter(|x| x != &i).collect(); match i != n - 1 { true => vec.insert(n - 2, i), false => vec.push(i), diff --git a/tests/reverse.rs b/tests/reverse.rs index 622af03..62f3f1f 100644 --- a/tests/reverse.rs +++ b/tests/reverse.rs @@ -14,7 +14,7 @@ fn list_reverse() { #[test] fn slice_reverse_empty() { for i in 0..20 { - let mut list = doubly::new_doubly(&mut &mut doubly::rng_with_seed(100 * i as u64), 20, 50); + let mut list = doubly::new_doubly(&mut doubly::rng_with_seed(100 * i as u64), 20, 50); let expected: Vec<_> = list.iter().cloned().collect(); let idx: Vec<_> = list.indices().collect(); @@ -30,7 +30,7 @@ fn slice_reverse_empty() { #[test] fn slice_reverse_single() { for i in 0..20 { - let mut list = doubly::new_doubly(&mut &mut doubly::rng_with_seed(100 * i as u64), 20, 50); + let mut list = doubly::new_doubly(&mut doubly::rng_with_seed(100 * i as u64), 20, 50); let expected: Vec<_> = list.iter().cloned().collect(); let idx: Vec<_> = list.indices().collect(); @@ -46,7 +46,7 @@ fn slice_reverse_single() { #[test] fn slice_reverse_from_front() { for i in 0..20 { - let mut list = doubly::new_doubly(&mut &mut doubly::rng_with_seed(100 * i as u64), 20, 50); + let mut list = doubly::new_doubly(&mut doubly::rng_with_seed(100 * i as u64), 20, 50); let mut expected: Vec<_> = list.iter().cloned().collect(); let idx: Vec<_> = list.indices().collect(); @@ -65,7 +65,7 @@ fn slice_reverse_from_front() { #[test] fn slice_reverse_until_back() { for i in 0..20 { - let mut list = doubly::new_doubly(&mut &mut doubly::rng_with_seed(100 * i as u64), 20, 50); + let mut list = doubly::new_doubly(&mut doubly::rng_with_seed(100 * i as u64), 20, 50); let mut expected: Vec<_> = list.iter().cloned().collect(); let idx: Vec<_> = list.indices().collect(); @@ -84,7 +84,7 @@ fn slice_reverse_until_back() { #[test] fn slice_reverse_middle() { for i in 0..20 { - let mut list = doubly::new_doubly(&mut &mut doubly::rng_with_seed(100 * i as u64), 20, 50); + let mut list = doubly::new_doubly(&mut doubly::rng_with_seed(100 * i as u64), 20, 50); let mut expected: Vec<_> = list.iter().cloned().collect(); let idx: Vec<_> = list.indices().collect(); diff --git a/tests/ring_iter_mut.rs b/tests/ring_iter_mut.rs index f17b266..ba8a372 100644 --- a/tests/ring_iter_mut.rs +++ b/tests/ring_iter_mut.rs @@ -57,7 +57,7 @@ fn ring_iter_mut_demo() { fn scan<'a, I: Iterator>(mut values: I) { if let Some(first) = values.next() { let mut acc = *first; - while let Some(x) = values.next() { + for x in values { let new_acc = acc + *x; *x += acc; acc = new_acc; diff --git a/tests/slice_doubly.rs b/tests/slice_doubly.rs index 18f1656..79aae9b 100644 --- a/tests/slice_doubly.rs +++ b/tests/slice_doubly.rs @@ -23,7 +23,7 @@ fn empty_from_nonempty() { let c = list.push_back('c'); assert!(list.eq_to_iter_vals(['a', 'b', 'c'])); - let indices = [a, b, c.clone()]; + let indices = [a, b, c]; for x in &indices { assert_empty_slice(&list.slice(x..x)); @@ -40,7 +40,7 @@ fn singleton_slice() { let expected = ['a', 'b', 'c']; assert!(list.eq_to_iter_refs(expected.iter())); - let indices = [a, b, c.clone()]; + let indices = [a, b, c]; for (i, x) in indices.iter().enumerate() { let slice = list.slice(x..=x); @@ -119,8 +119,8 @@ fn doubly_slice() { let idx: Vec<_> = list.indices().collect(); // empty - for i in 0..n { - assert_empty_slice(&list.slice(idx[i]..idx[i])); + for id in idx.iter().take(n) { + assert_empty_slice(&list.slice(id..id)); } // single diff --git a/tests/slice_move_next_to.rs b/tests/slice_move_next_to.rs index 22acd48..d6e5ee9 100644 --- a/tests/slice_move_next_to.rs +++ b/tests/slice_move_next_to.rs @@ -23,7 +23,7 @@ fn slice_move_next_to_front() { #[cfg(feature = "validation")] list.validate(); - let mut vec: Vec<_> = (0..n).into_iter().filter(|x| x != &i).collect(); + let mut vec: Vec<_> = (0..n).filter(|x| x != &i).collect(); vec.insert(a + 1, i); assert_eq!(slice, &vec[a..=b]); @@ -48,7 +48,7 @@ fn slice_move_next_to_back() { #[cfg(feature = "validation")] list.validate(); - let mut vec: Vec<_> = (0..n).into_iter().filter(|x| x != &i).collect(); + let mut vec: Vec<_> = (0..n).filter(|x| x != &i).collect(); vec.insert(b, i); assert_eq!(slice, &vec[a..=b]); diff --git a/tests/slice_move_prev_to.rs b/tests/slice_move_prev_to.rs index 72470d0..5cee7ec 100644 --- a/tests/slice_move_prev_to.rs +++ b/tests/slice_move_prev_to.rs @@ -23,7 +23,7 @@ fn slice_move_prev_to_front() { #[cfg(feature = "validation")] list.validate(); - let mut vec: Vec<_> = (0..n).into_iter().filter(|x| x != &i).collect(); + let mut vec: Vec<_> = (0..n).filter(|x| x != &i).collect(); vec.insert(a, i); assert_eq!(slice, &vec[a..=b]); @@ -48,7 +48,7 @@ fn slice_move_prev_to_back() { #[cfg(feature = "validation")] list.validate(); - let mut vec: Vec<_> = (0..n).into_iter().filter(|x| x != &i).collect(); + let mut vec: Vec<_> = (0..n).filter(|x| x != &i).collect(); match i != b { true => vec.insert(b - 1, i), false => vec.insert(b, i), diff --git a/tests/slice_mut_doubly.rs b/tests/slice_mut_doubly.rs index c3dc214..c1b7012 100644 --- a/tests/slice_mut_doubly.rs +++ b/tests/slice_mut_doubly.rs @@ -23,7 +23,7 @@ fn empty_from_nonempty() { let c = list.push_back('c'); assert!(list.eq_to_iter_vals(['a', 'b', 'c'])); - let indices = [a, b, c.clone()]; + let indices = [a, b, c]; for x in &indices { assert_empty_slice(&list.slice_mut(x..x)); @@ -39,7 +39,7 @@ fn singleton_slice() { let expected = ['x', 'y', 'z']; - let indices = [a, b, c.clone()]; + let indices = [a, b, c]; for (i, x) in indices.iter().copied().enumerate() { let mut slice = list.slice_mut(x..=x);