1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
use crate::Number;
use super::Term;

///A struct assigning to each piece of the function a time after which it is applicable. The term
///will be the evluated one until t passes the next part's after value
struct PiecewisePair<T: Number>
{

    term: Box<dyn Term<T>>,
    after: T //The time after which to apply the term

}

///Struct containing a list of terms and times which split the number line into intervals during
///which different terms are applied
pub struct PiecewiseTerm<T: Number>
{

    parts: Vec<PiecewisePair<T>>

}

impl<T: Number> PiecewiseTerm<T>
{

    ///Creates a PiecewiseTerm, which is initialized to contain no terms. Terms and times must be
    ///added using add_part
    pub fn new() -> PiecewiseTerm<T>
    {

        return PiecewiseTerm { parts: Vec::new() };

    }

    ///Adds on a term to the piecewise function.
    ///
    /// # Examples
    ///
    /// ```
    /// use crate::parametrizer::term::piecewiseterm::PiecewiseTerm;
    /// use crate::parametrizer::term::constantterm::ConstantTerm;
    /// use crate::parametrizer::term::Term;
    ///
    /// let mut piecewise = PiecewiseTerm::new();
    ///
    /// let const1 = ConstantTerm::new(3);
    /// let const2 = ConstantTerm::new(5);
    /// let const3 = ConstantTerm::new(9);
    ///
    /// piecewise.add_part(Box::new(const1), 0);
    /// piecewise.add_part(Box::new(const2), 5);
    /// piecewise.add_part(Box::new(const3), 10);
    ///
    /// assert_eq!(3, piecewise.evaluate(2));
    /// assert_eq!(5, piecewise.evaluate(8));
    /// assert_eq!(9, piecewise.evaluate(20));
    /// ```
    pub fn add_part(&mut self, term: Box<dyn Term<T>>, after: T)
    {

        self.parts.push(PiecewisePair::<T> { term, after });

    }

}

impl<T: Number> Term<T> for PiecewiseTerm<T>
{

    ///Iterates through all of the piecewise parts, returning the evluation of the term assigned to
    ///the the interval containing t
    fn evaluate(&self, t: T) -> T
    {

        let mut iter = self.parts.iter();

        let mut current = match iter.next()
        {

            Some(t) => &t.term,
            None => return T::zero()

        };

        for part in iter
        {

            if t >= part.after
            {

                current = &part.term;

            }
            else
            {

                return current.evaluate(t);

            }

        }

        return current.evaluate(t);

    }

}