partial_function

[Done] Partial Function library for Rust.
git clone https://git.jojolepro.com/partial_function.git
Log | Files | Refs | README | LICENSE

commit 3de76e4fca95c089550f297f6b74c85776c3e51a
parent 134aa92d1cbabf909b91cc9155ab4a5741dad3fe
Author: jojo <jojolepromain@gmail.com>
Date:   Wed, 27 Sep 2017 14:40:31 -0400

Made all the things generic ;)

Diffstat:
Msrc/lib.rs | 45+++++++++++++++++++++++++--------------------
Mtests/tests.rs | 12++++++------
2 files changed, 31 insertions(+), 26 deletions(-)

diff --git a/src/lib.rs b/src/lib.rs @@ -4,13 +4,14 @@ use std::f32; /// A regular function that is only defined between lower and higher. /// If two functions intersect their higher and lower bounds respectively. /// The second will take precedence where f(lower). -pub struct BoundedFunction { +pub struct BoundedFunction<B,O> +where B:PartialOrd{ /// The stored function f(x) = ??? - pub func: fn(f32) -> f32, + pub func: fn(B) -> O, /// The lower bound of the function. - pub lower: f32, + pub lower: B, /// The higher bound of the function. - pub higher: f32, + pub higher: B, } /// Define a functions defined by multiple functions parts. @@ -18,19 +19,21 @@ pub struct BoundedFunction { /// Uses bounds as [lower,higher], /// except in the case of a lower bound overlapping a higher bound. /// In this case, the lower bound always take precedence. -pub struct PartialFunction { - funcs: Vec<BoundedFunction>, +pub struct PartialFunction<B,O> +where B:PartialOrd{ + funcs: Vec<BoundedFunction<B,O>>, } -impl PartialFunction { +impl<B,O> PartialFunction<B,O> +where B:PartialOrd{ /// Creates a new PartialFunctionBuilder - pub fn new() -> PartialFunctionBuilder { + pub fn new() -> PartialFunctionBuilder<B,O> { PartialFunctionBuilder::new() } /// Evaluates the partial function. /// Returns NAN if no function is defined. - pub fn eval(&self, x: f32) -> f32 { + pub fn eval(&self, x: B) -> Option<O> { let iter = self.funcs.iter().enumerate(); for (i, bounded) in iter { let next = self.funcs.get(i + 1); @@ -39,46 +42,48 @@ impl PartialFunction { (next.is_some() && next.unwrap().lower != bounded.higher) { let f = bounded.func; - return f(x); + return Some(f(x)); } } - f32::NAN + None } } /// A builder to create an immutable PartialFunction. -pub struct PartialFunctionBuilder { - funcs: Vec<BoundedFunction>, +pub struct PartialFunctionBuilder<B,O> +where B:PartialOrd{ + funcs: Vec<BoundedFunction<B,O>>, } -impl PartialFunctionBuilder { +impl<B,O> PartialFunctionBuilder<B,O> +where B:PartialOrd{ /// Creates a new PartialFunctionBuilder. pub fn new() -> Self { PartialFunctionBuilder { funcs: vec![] } } /// Adds a bounded function bounded between [lower,higher[ of function func. - pub fn with(mut self, lower: f32, higher: f32, func: fn(f32) -> f32) -> Self { + pub fn with(mut self, lower: B, higher: B, func: fn(B) -> O) -> Self { + debug_assert!(self.can_insert(&lower, &higher)); let f = BoundedFunction { func: func, lower: lower, higher: higher, }; - debug_assert!(self.can_insert(lower, higher)); self.funcs.push(f); self } /// Check if you can safely insert into the function list for the specified bounds. - pub fn can_insert(&self, lower: f32, higher: f32) -> bool { + pub fn can_insert(&self, lower: &B, higher: &B) -> bool { !self.funcs.iter().any(|b| { - (lower >= b.lower && lower < b.higher) || (higher > b.lower && higher <= b.higher) || - (lower <= b.lower && higher >= b.higher) + (lower >= &b.lower && lower < &b.higher) || (higher > &b.lower && higher <= &b.higher) || + (lower <= &b.lower && higher >= &b.higher) }) } /// Builds the PartialFunction from the functions added using with. - pub fn build(mut self) -> PartialFunction { + pub fn build(mut self) -> PartialFunction<B,O> { self.funcs.sort_by(|a, b| { a.lower .partial_cmp(&b.lower) diff --git a/tests/tests.rs b/tests/tests.rs @@ -7,22 +7,22 @@ mod tests { #[test] fn single() { let p = PartialFunction::new().with(0.0, 1.0, |x| x).build(); - assert_eq!(0.5, p.eval(0.5)); + assert_eq!(Some(0.5), p.eval(0.5)); } #[test] fn single_start() { let p = PartialFunction::new().with(0.0, 1.0, |x| x).build(); - assert_eq!(0.0, p.eval(0.0)); + assert_eq!(Some(0.0), p.eval(0.0)); } #[test] fn single_ending() { let p = PartialFunction::new().with(0.0, 1.0, |x| x).build(); - assert_eq!(1.0, p.eval(1.0)); + assert_eq!(Some(1.0), p.eval(1.0)); } #[test] fn single_nan() { let p = PartialFunction::new().with(0.0, 1.0, |x| x).build(); - assert!(p.eval(999.0).is_nan()); + assert!(p.eval(999.0).is_none()); } #[test] fn dual_start() { @@ -30,7 +30,7 @@ mod tests { .with(1.0, 2.0, |x| 5.0) .with(0.0, 1.0, |x| x) .build(); - assert_eq!(5.0, p.eval(1.0)); + assert_eq!(Some(5.0), p.eval(1.0)); } #[test] fn dual_end() { @@ -38,7 +38,7 @@ mod tests { .with(0.0, 1.0, |x| x) .with(1.0, 2.0, |x| 5.0) .build(); - assert_eq!(5.0, p.eval(1.0)); + assert_eq!(Some(5.0), p.eval(1.0)); } #[test] #[should_panic]