From c1b486c4f1ff28a00e9a03222bc63821e216644f Mon Sep 17 00:00:00 2001 From: AshrafIbrahim03 Date: Mon, 17 Aug 2026 15:36:56 -0400 Subject: [PATCH 1/5] Added sorted iterator --- src/lib.rs | 1 + src/sorted_iterator.rs | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/sorted_iterator.rs diff --git a/src/lib.rs b/src/lib.rs index 1c9bfeaa..073dca49 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,5 +65,6 @@ pub mod euclid; pub mod function; pub mod generate; pub mod prec; +pub mod sorted_iterator; pub mod statistics; pub mod stats_tests; diff --git a/src/sorted_iterator.rs b/src/sorted_iterator.rs new file mode 100644 index 00000000..6c02270f --- /dev/null +++ b/src/sorted_iterator.rs @@ -0,0 +1,38 @@ +use std::marker::PhantomData; + +use crate::stats_tests::NaNPolicy; + +pub trait SortedIterator { + fn sorted_iter(&self, policy: NaNPolicy) -> Sorted; +} + +impl SortedIterator for Vec { + fn sorted_iter(&self, policy: NaNPolicy) -> Sorted { + Sorted::new(self, policy) + } +} + +/// TODO iron out implementation details later because this is not optimal retrieval of sorted data +pub struct Sorted { + sorted_iter: std::vec::IntoIter, + policy: NaNPolicy, +} + +impl Sorted { + pub fn new(data: &[f64], policy: NaNPolicy) -> Self { + let mut cloned = Vec::from(data); + cloned.sort_by(|a, b| a.total_cmp(b)); + Self { + sorted_iter: cloned.into_iter(), + policy, + } + } +} + +impl Iterator for Sorted { + type Item = f64; + + fn next(&mut self) -> Option { + self.sorted_iter.next() + } +} From e24648c7c620b6edeb515469baeacf9ac870bbd2 Mon Sep 17 00:00:00 2001 From: AshrafIbrahim03 Date: Fri, 28 Aug 2026 09:38:54 -0400 Subject: [PATCH 2/5] Added sorted collection validation --- src/lib.rs | 1 + src/sorted_collection.rs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/sorted_collection.rs diff --git a/src/lib.rs b/src/lib.rs index 073dca49..71ec5284 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,6 +65,7 @@ pub mod euclid; pub mod function; pub mod generate; pub mod prec; +pub mod sorted_collection; pub mod sorted_iterator; pub mod statistics; pub mod stats_tests; diff --git a/src/sorted_collection.rs b/src/sorted_collection.rs new file mode 100644 index 00000000..97c85be3 --- /dev/null +++ b/src/sorted_collection.rs @@ -0,0 +1,19 @@ +pub enum SortError { + NotSorted, +} + +pub struct SortedCollection<'a, T> { + sorted: &'a [T], +} + +impl<'a, T> SortedCollection<'a, T> +where + T: PartialOrd, +{ + pub fn new(coll: &'a [T]) -> Result { + match coll.windows(2).all(|sl| sl[0] < sl[1]) { + true => Ok(Self { sorted: coll }), + false => Err(SortError::NotSorted), + } + } +} From 4f9b16130ff6851ac69f061f0432c46150866faf Mon Sep 17 00:00:00 2001 From: AshrafIbrahim03 Date: Fri, 28 Aug 2026 09:43:30 -0400 Subject: [PATCH 3/5] Added iterator function to SortedCollection --- src/sorted_collection.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sorted_collection.rs b/src/sorted_collection.rs index 97c85be3..5c23f316 100644 --- a/src/sorted_collection.rs +++ b/src/sorted_collection.rs @@ -16,4 +16,7 @@ where false => Err(SortError::NotSorted), } } + pub fn iter(&self) -> std::slice::Iter<'a, T> { + self.sorted.iter() + } } From 68c13e12a3720fd56d7120308dfa84a060552ba1 Mon Sep 17 00:00:00 2001 From: AshrafIbrahim03 Date: Fri, 28 Aug 2026 10:16:54 -0400 Subject: [PATCH 4/5] Added convenience methods for instantiating SortedCollection --- src/sorted_collection.rs | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/sorted_collection.rs b/src/sorted_collection.rs index 5c23f316..c51889d4 100644 --- a/src/sorted_collection.rs +++ b/src/sorted_collection.rs @@ -1,22 +1,43 @@ +use std::cmp::Ordering; + pub enum SortError { NotSorted, } +pub enum Collection<'a, T> { + Ref(&'a [T]), + Owned(Vec), +} + pub struct SortedCollection<'a, T> { - sorted: &'a [T], + sorted: Collection<'a, T>, } impl<'a, T> SortedCollection<'a, T> where - T: PartialOrd, + T: PartialOrd + Ord, { - pub fn new(coll: &'a [T]) -> Result { - match coll.windows(2).all(|sl| sl[0] < sl[1]) { - true => Ok(Self { sorted: coll }), + pub fn from_slice(coll: &'a [T]) -> Result { + match coll + .windows(2) + .all(|sl| sl[0].cmp(&sl[1]) == Ordering::Less) + { + true => Ok(Self { + sorted: Collection::Ref(coll), + }), false => Err(SortError::NotSorted), } } - pub fn iter(&self) -> std::slice::Iter<'a, T> { - self.sorted.iter() + pub fn from_mut_vec(mut coll: Vec) -> Result { + coll.sort(); + Ok(Self { + sorted: Collection::Owned(coll), + }) + } + pub fn iter(&'a self) -> std::slice::Iter<'a, T> { + match self.sorted { + Collection::Ref(items) => items.iter(), + Collection::Owned(ref items) => items.iter(), + } } } From b44e42c1962c7eb9d8c9d33af0a1975c93434ae2 Mon Sep 17 00:00:00 2001 From: AshrafIbrahim03 Date: Fri, 28 Aug 2026 10:57:43 -0400 Subject: [PATCH 5/5] Added convenience derives and conversion functions --- src/sorted_collection.rs | 41 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/src/sorted_collection.rs b/src/sorted_collection.rs index c51889d4..4cae1b0a 100644 --- a/src/sorted_collection.rs +++ b/src/sorted_collection.rs @@ -4,18 +4,20 @@ pub enum SortError { NotSorted, } +#[derive(Clone, Debug)] pub enum Collection<'a, T> { Ref(&'a [T]), Owned(Vec), } +#[derive(Clone, Debug)] pub struct SortedCollection<'a, T> { sorted: Collection<'a, T>, } impl<'a, T> SortedCollection<'a, T> where - T: PartialOrd + Ord, + T: Ord, { pub fn from_slice(coll: &'a [T]) -> Result { match coll @@ -28,11 +30,11 @@ where false => Err(SortError::NotSorted), } } - pub fn from_mut_vec(mut coll: Vec) -> Result { + pub fn from_mut_vec(mut coll: Vec) -> Self { coll.sort(); - Ok(Self { + Self { sorted: Collection::Owned(coll), - }) + } } pub fn iter(&'a self) -> std::slice::Iter<'a, T> { match self.sorted { @@ -41,3 +43,34 @@ where } } } + +impl<'a, T> TryFrom<&'a [T]> for SortedCollection<'a, T> +where + T: Ord, +{ + type Error = SortError; + + fn try_from(value: &'a [T]) -> Result { + Self::from_slice(value) + } +} + +impl<'a, T> TryFrom<&'a Box<[T]>> for SortedCollection<'a, T> +where + T: Ord, +{ + type Error = SortError; + + fn try_from(value: &'a Box<[T]>) -> Result { + Self::from_slice(value.as_ref()) + } +} + +impl<'a, T> AsRef<[T]> for SortedCollection<'a, T> { + fn as_ref(&self) -> &[T] { + match self.sorted { + Collection::Ref(items) => items, + Collection::Owned(ref items) => items.as_ref(), + } + } +}