From e90555e7bbc4bfda4d5a92631e2dfdf265ddae4f Mon Sep 17 00:00:00 2001 From: LukeMathWalker Date: Sun, 2 Sep 2018 14:41:15 +0100 Subject: [PATCH 1/4] Implemented Midpoint. Refactored code to change types of variables. --- src/numeric/impl_numeric.rs | 47 +++++++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/src/numeric/impl_numeric.rs b/src/numeric/impl_numeric.rs index 6ad427fcb..fab40e406 100644 --- a/src/numeric/impl_numeric.rs +++ b/src/numeric/impl_numeric.rs @@ -6,8 +6,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::ops::Add; -use libnum::{self, Zero, Float}; +use std::ops::{Add, Div}; +use libnum::{self, Zero, Float, FromPrimitive}; use itertools::free::enumerate; use imp_prelude::*; @@ -36,12 +36,17 @@ pub trait Interpolate { } fn needs_lower(q: f64, len: usize) -> bool; fn needs_upper(q: f64, len: usize) -> bool; - fn interpolate(lower: Option, upper: Option, q: f64, len: usize) -> T; + fn interpolate(lower: Option>, + upper: Option>, + q: f64, + len: usize) -> Array + where D: Dimension; } pub struct Upper; pub struct Lower; pub struct Nearest; +pub struct Midpoint; impl Interpolate for Upper { fn needs_lower(_q: f64, _len: usize) -> bool { @@ -50,7 +55,10 @@ impl Interpolate for Upper { fn needs_upper(_q: f64, _len: usize) -> bool { true } - fn interpolate(_lower: Option, upper: Option, _q: f64, _len: usize) -> T { + fn interpolate(_lower: Option>, + upper: Option>, + _q: f64, + _len: usize) -> Array { upper.unwrap() } } @@ -62,7 +70,10 @@ impl Interpolate for Lower { fn needs_upper(_q: f64, _len: usize) -> bool { false } - fn interpolate(lower: Option, _upper: Option, _q: f64, _len: usize) -> T { + fn interpolate(lower: Option>, + _upper: Option>, + _q: f64, + _len: usize) -> Array { lower.unwrap() } } @@ -75,7 +86,10 @@ impl Interpolate for Nearest { fn needs_upper(q: f64, len: usize) -> bool { !>::needs_lower(q, len) } - fn interpolate(lower: Option, upper: Option, q: f64, len: usize) -> T { + fn interpolate(lower: Option>, + upper: Option>, + q: f64, + len: usize) -> Array { if >::needs_lower(q, len) { lower.unwrap() } else { @@ -84,6 +98,25 @@ impl Interpolate for Nearest { } } +impl Interpolate for Midpoint + where T: Add + Div + Clone + FromPrimitive +{ + fn needs_lower(_q: f64, _len: usize) -> bool { + true + } + fn needs_upper(_q: f64, _len: usize) -> bool { + true + } + fn interpolate(lower: Option>, + upper: Option>, + _q: f64, _len: usize) -> Array + where D: Dimension + { + let denom = T::from_u8(2).unwrap(); + (lower.unwrap() + upper.unwrap()).mapv_into(|x| x / denom.clone()) + } +} + /// Numerical methods for arrays. impl ArrayBase where S: Data, @@ -214,7 +247,7 @@ impl ArrayBase where D: RemoveAxis, A: Ord + Clone + Zero, S: DataMut, - I: Interpolate>, + I: Interpolate, { assert!((0. <= q) && (q <= 1.)); let mut lower = None; From 1d094e8f5f966b539be9d0b5845c1586ecd251c4 Mon Sep 17 00:00:00 2001 From: LukeMathWalker Date: Sun, 2 Sep 2018 15:01:30 +0100 Subject: [PATCH 2/4] Defined Linear. --- src/numeric/impl_numeric.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/numeric/impl_numeric.rs b/src/numeric/impl_numeric.rs index fab40e406..9b717bef3 100644 --- a/src/numeric/impl_numeric.rs +++ b/src/numeric/impl_numeric.rs @@ -47,6 +47,19 @@ pub struct Upper; pub struct Lower; pub struct Nearest; pub struct Midpoint; +pub struct Linear { + coeff: T, +} + +impl Linear + where T: FromPrimitive + Ord +{ + pub fn new(coeff: T) -> Self { + assert!(coeff <= T::from_u8(1).unwrap()); + assert!(coeff >= T::from_u8(0).unwrap()); + Linear { coeff } + } +} impl Interpolate for Upper { fn needs_lower(_q: f64, _len: usize) -> bool { From f5f77eab7b1be188aa23da95113728f471b60ac4 Mon Sep 17 00:00:00 2001 From: LukeMathWalker Date: Sun, 2 Sep 2018 15:15:58 +0100 Subject: [PATCH 3/4] Added Interpolate implementation for Linear. --- src/numeric/impl_numeric.rs | 44 +++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/src/numeric/impl_numeric.rs b/src/numeric/impl_numeric.rs index 9b717bef3..d97098340 100644 --- a/src/numeric/impl_numeric.rs +++ b/src/numeric/impl_numeric.rs @@ -6,7 +6,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::ops::{Add, Div}; +use std::ops::{Add, Sub, Div, Mul}; use libnum::{self, Zero, Float, FromPrimitive}; use itertools::free::enumerate; @@ -34,6 +34,11 @@ pub trait Interpolate { fn upper_index(q: f64, len: usize) -> usize { Self::float_percentile_index(q, len).ceil() as usize } + + fn float_percentile_index_fraction(q: f64, len: usize) -> f64 { + Self::float_percentile_index(q, len) - (Self::lower_index(q, len) as f64) + } + fn needs_lower(q: f64, len: usize) -> bool; fn needs_upper(q: f64, len: usize) -> bool; fn interpolate(lower: Option>, @@ -47,19 +52,7 @@ pub struct Upper; pub struct Lower; pub struct Nearest; pub struct Midpoint; -pub struct Linear { - coeff: T, -} - -impl Linear - where T: FromPrimitive + Ord -{ - pub fn new(coeff: T) -> Self { - assert!(coeff <= T::from_u8(1).unwrap()); - assert!(coeff >= T::from_u8(0).unwrap()); - Linear { coeff } - } -} +pub struct Linear; impl Interpolate for Upper { fn needs_lower(_q: f64, _len: usize) -> bool { @@ -130,6 +123,29 @@ impl Interpolate for Midpoint } } +impl Interpolate for Linear + where T: Add + Sub + Mul + Clone + FromPrimitive +{ + fn needs_lower(_q: f64, _len: usize) -> bool { + true + } + fn needs_upper(_q: f64, _len: usize) -> bool { + true + } + fn interpolate(lower: Option>, + upper: Option>, + q: f64, len: usize) -> Array + where D: Dimension + { + let fraction = T::from_f64( + >::float_percentile_index_fraction(q, len) + ).unwrap(); + let a = lower.unwrap().mapv_into(|x| x * fraction.clone()); + let b = upper.unwrap().mapv_into(|x| x * (T::from_u8(1).unwrap() - fraction.clone())); + a + b + } +} + /// Numerical methods for arrays. impl ArrayBase where S: Data, From ff51479c42e7904abd4807fe7b85d6bc64699d9c Mon Sep 17 00:00:00 2001 From: LukeMathWalker Date: Sun, 2 Sep 2018 15:21:50 +0100 Subject: [PATCH 4/4] Fixed docs! --- src/numeric/impl_numeric.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/numeric/impl_numeric.rs b/src/numeric/impl_numeric.rs index d97098340..e5638e249 100644 --- a/src/numeric/impl_numeric.rs +++ b/src/numeric/impl_numeric.rs @@ -249,8 +249,8 @@ impl ArrayBase /// as the element that would be indexed as `(N-1)q` if the lane were to be sorted /// in increasing order. /// If `(N-1)q` is not an integer the desired percentile lies between - /// two data points: we return the lower, nearest or higher datapoint depending - /// on `interpolation_strategy`. + /// two data points: we return the lower, nearest, higher or interpolated + /// value depending on the type `Interpolate` bound `I`. /// /// Some examples: /// - `q=0.` returns the minimum along each 1-dimensional lane;