use core::ops::Div;
use core::ops::Mul;
use crate::ivs::endpoint_map::IntervalsEndpointMap;
pub struct IntervalStretch;
impl IntervalStretch {
#[allow(clippy::new_ret_no_self)]
pub fn new<Is, Ev>(
intervals: Is,
factor: Ev,
) -> IntervalsEndpointMap<Is, impl Fn(Ev) -> Ev + Clone, impl Fn(Ev) -> Ev + Clone, Ev, Ev>
where
Ev: Mul<Output = Ev> + Div<Output = Ev> + Clone + Default + PartialOrd,
{
assert!(factor > Ev::default(), "factor must be positive");
let f_fwd = factor.clone();
let f_inv = factor;
IntervalsEndpointMap::new(
intervals,
move |v: Ev| v * f_fwd.clone(),
move |v: Ev| v / f_inv.clone(),
)
}
}
#[cfg(test)]
mod tests {
use crate::EndpointOC;
use crate::Interval;
use crate::IntervalStretch;
use crate::Intervals;
use crate::IntervalsSingle;
#[test]
fn stretch_test() {
let i = Interval::new(EndpointOC::Closed(1), EndpointOC::Open(4), ());
let is = IntervalsSingle::new(i);
let mut ism = IntervalStretch::new(is, 3);
let a = ism.head(None);
let expected = Interval::new(EndpointOC::Closed(3), EndpointOC::Open(12), ());
assert!(a == Some(expected));
let a = ism.head(Some(crate::LeftT::Left(EndpointOC::Closed(6))));
let expected = Interval::new(EndpointOC::Closed(6), EndpointOC::Open(12), ());
assert!(a == Some(expected));
let a = ism.head(Some(crate::LeftT::Left(EndpointOC::Closed(12))));
let expected = None;
assert!(a == expected);
}
#[test]
#[should_panic(expected = "factor must be positive")]
fn zero_factor_panics() {
let i = Interval::new(EndpointOC::Closed(1), EndpointOC::Open(4), ());
let is = IntervalsSingle::new(i);
let _ = IntervalStretch::new(is, 0);
}
#[test]
#[should_panic(expected = "factor must be positive")]
fn negative_factor_panics() {
let i = Interval::new(EndpointOC::Closed(1), EndpointOC::Open(4), ());
let is = IntervalsSingle::new(i);
let _ = IntervalStretch::new(is, -1);
}
}