diff --git a/Cargo.toml b/Cargo.toml index 9004244..44636db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "medians" -version = "3.0.5" +version = "3.0.6" authors = ["Libor Spacek"] edition = "2021" description = "Median, Statistical Measures, Mathematics, Statistics" diff --git a/README.md b/README.md index 58af5ab..d79158f 100644 --- a/README.md +++ b/README.md @@ -109,6 +109,8 @@ pub trait Median<'a, T> { ## Release Notes +**Version 3.0.6** - Moved `part`, `ref_vec` and `deref_vec` into crate `Indxvec`, to allow their wider use. + **Version 3.0.5** - Obsolete code pruning. **Version 3.0.4** - Some minor code simplifications. diff --git a/src/algos.rs b/src/algos.rs index 9c84e69..2a52afb 100644 --- a/src/algos.rs +++ b/src/algos.rs @@ -1,10 +1,6 @@ use core::cmp::{Ordering, Ordering::*}; use std::ops::Range; - -/// Constructs ref wrapped `Vec<&T>` from `&[T] in rng` -pub fn ref_vec(v: &[T], rng: Range) -> Vec<&T> { - v.iter().take(rng.end).skip(rng.start).collect() -} +use indxvec::Mutops; /// Index of the middling value of four refs. Makes only three comparisons fn middling( @@ -80,39 +76,6 @@ pub fn qbalance(s: &[T], centre: &f64, q: impl Fn(&T) -> f64) -> i64 { 1 } -/// Partitions `s: &mut [&T]` within range `rng`, using comparator `c`. -/// The first item `s[rng.start]` is assumed to be the pivot. -/// The three rearranged partitions are demarcated by eqstart,gtstart, where: -/// `rng.start..eqstart` (may be empty) contains refs to items lesser than the pivot, -/// `gtstart-eqstart` is the number (>= 1) of items equal to the pivot (values within this subrange are undefined) -/// `gtstart..rng.end` (may be empty) contains refs to items greater than the pivot. -pub fn part( - s: &mut [&T], - rng: &Range, - c: &mut impl FnMut(&T, &T) -> Ordering, -) -> (usize, usize) { - // get pivot from the first location - let pivot = s[rng.start]; - let mut eqstart = rng.start; - let mut gtstart = eqstart + 1; - for t in rng.start + 1..rng.end { - match c(s[t], pivot) { - Less => { - s[eqstart] = s[t]; - eqstart += 1; - s[t] = s[gtstart]; - gtstart += 1; - } - Equal => { - s[t] = s[gtstart]; - gtstart += 1; - } - Greater => (), - } - } - (eqstart, gtstart) -} - /// Odd median of `&[u8]` pub fn oddmedianu8(s: &[u8]) -> f64 { let need = s.len() / 2; // median target position @@ -183,7 +146,7 @@ pub fn oddmedian_by<'a, T>(s: &mut [&'a T], c: &mut impl FnMut(&T, &T) -> Orderi s.swap(rng.start, pivotsub); }; let pivotref = s[rng.start]; - let (eqsub, gtsub) = part(s, &rng, c); + let (eqsub, gtsub) = <&mut [T]>::part(s, &rng, c); // well inside lt partition, iterate on it if need + 2 < eqsub { rng.end = eqsub; @@ -235,7 +198,7 @@ pub fn evenmedian_by<'a, T>( s.swap(rng.start, pivotsub); }; let pivotref = s[rng.start]; - let (eqsub, gtsub) = part(s, &rng, c); + let (eqsub, gtsub) = <&mut [T]>::part(s, &rng, c); // well inside lt partition, iterate on it narrowing the range if need + 2 < eqsub { rng.end = eqsub; diff --git a/src/lib.rs b/src/lib.rs index 4928e8c..63ff1cc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,7 +15,7 @@ use crate::algos::*; pub use crate::error::{merror, MedError}; use core::{cmp::Ordering, fmt::Display}; -use indxvec::printing::{GR, UN, YL}; +use indxvec::{Vecops,printing::{GR, UN, YL}}; /// Shorthand type for medians errors with message payload specialized to String pub type Me = MedError; @@ -141,7 +141,7 @@ impl Medianf64 for &[f64] { 2 => return (self[0] + self[1]) / 2.0, _ => (), }; - let mut s = ref_vec(self, 0..self.len()); + let mut s = self.ref_vec(0..self.len()); if (n & 1) == 1 { let oddm = oddmedian_by(&mut s, &mut ::total_cmp); *oddm @@ -211,7 +211,7 @@ impl<'a, T> Median<'a, T> for &'a [T] { 2 => return Ok((q(&self[0]) + q(&self[1])) / 2.0), _ => (), }; - let mut s = ref_vec(self, 0..self.len()); + let mut s = self.ref_vec(0..self.len()); if (n & 1) == 1 { Ok(q(oddmedian_by(&mut s, c))) } else { @@ -229,7 +229,7 @@ impl<'a, T> Median<'a, T> for &'a [T] { 2 => return Ok(Medians::Even((&self[0], &self[1]))), _ => (), }; - let mut s = ref_vec(self, 0..self.len()); + let mut s = self.ref_vec(0..self.len()); if (n & 1) == 1 { Ok(Medians::Odd(oddmedian_by(&mut s, c))) } else { diff --git a/src/oldalgos.rs b/src/oldalgos.rs index 128b1f9..25cb086 100644 --- a/src/oldalgos.rs +++ b/src/oldalgos.rs @@ -50,14 +50,6 @@ pub fn to_f64s(v: &[u64]) -> Vec { v.iter().map(|&u| to_f64(u)).collect() } -/// Builds Vec from refs in Vec<&T> (inverse of ref_vec()) -pub fn deref_vec(v: &[&T]) -> Vec -where - T: Clone, -{ - v.iter().map(|&x| x.clone()).collect() -} - /// Maps general `quantify` closure to self, converting the type T -> U pub fn quant_vec(v: &[T], quantify: impl Fn(&T) -> U) -> Vec { v.iter().map(quantify).collect::>() diff --git a/tests/tests.rs b/tests/tests.rs index 4156da9..da8eadc 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -2,7 +2,7 @@ #![allow(dead_code)] #[cfg(test)] use indxvec::{here, printing::*, Indices, Mutops, Printing, Vecops}; -use medians::algos::{qbalance, part, ref_vec, min, min2}; +use medians::algos::{qbalance, min, min2}; // use medians::algosf64::partord; use medians::{Me, merror, medianu8, Median, Medianf64}; use ran:: *; @@ -22,8 +22,8 @@ fn parting() -> Result<(), Me> { // println!("Scrubbed: {}", scrub_nans(&to_f64s(&to_u64s(&data))).gr()); let len = data.len(); println!("Pivot {}: {}", data[0].yl(), data.gr()); - let mut refdata = ref_vec(&data, 0..len); - let (eqsub, gtsub) = part( + let mut refdata = data.ref_vec(0..len); + let (eqsub, gtsub) = <&mut [f64]>::part( &mut refdata, &(0..len), &mut ::total_cmp, @@ -75,10 +75,10 @@ fn medf64() -> Result<(), Me> { ]; println!("Data: {}",v.gr()); let len = v.len(); - let mut vr = ref_vec(&v,0..len); + let mut vr = v.ref_vec(0..len); println!("max: {}",min(&vr,0..len,&mut |a:&f64,b:&f64| b.total_cmp(a)).gr()); println!("max2: {}",min2(&vr,0..len,&mut |a:&f64,b:&f64| b.total_cmp(a)).gr()); - let (eqsub,gtsub) = part( + let (eqsub,gtsub) = <&mut [f64]>::part( &mut vr, &(0..v.len()), &mut ::total_cmp,