summaryrefslogtreecommitdiff
path: root/src/lerp.rs
blob: b5b771d1498a9aef24daccdb949b41e08444a139 (plain)
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
use crate::poly::Poly;
use std::rc::Rc;

#[derive(PartialEq, Debug)]
pub enum Lerp {
    Node(Rc<Lerp>, Rc<Lerp>),
    Leaf(f32, f32),
    Just(f32),
}

impl Lerp {
    pub fn new(v: &Vec<f32>) -> Rc<Lerp> {
        match v.len() {
            0 => Rc::new(Lerp::Just(0.0)),
            1 => Rc::new(Lerp::Just(v[0])),
            2 => Rc::new(Lerp::Leaf(v[0], v[1])),
            _ => {
                let mut lv = Vec::new();
                for i in 0..v.len() - 1 {
                    lv.push(Rc::new(Lerp::Leaf(v[i], v[i + 1])));
                }
                while lv.len() > 1 {
                    let mut nlv = Vec::new();
                    for i in 0..lv.len() - 1 {
                        nlv.push(Rc::new(Lerp::Node(lv[i].clone(), lv[i + 1].clone())));
                    }
                    lv = nlv;
                }
                lv[0].clone()
            }
        }
    }

    pub fn to_poly(&self) -> Poly {
        match self {
            Lerp::Just(a) => Poly::new(vec![*a]),
            Lerp::Leaf(a, b) => Poly::new(vec![*a, *b - *a]),
            Lerp::Node(a, b) => {
                let a = a.to_poly();
                let b = b.to_poly();
                let c = &b - &a;
                &a + &c.shift()
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn new2_test() {
        let a = Lerp::new(&vec![1.0, 2.0]);
        assert_eq!(a, Rc::new(Lerp::Leaf(1.0, 2.0)));
    }

    #[test]
    fn new3_test() {
        let a = Lerp::new(&vec![1.0, 2.0, 3.0]);
        assert_eq!(
            a,
            Rc::new(Lerp::Node(
                Rc::new(Lerp::Leaf(1.0, 2.0)),
                Rc::new(Lerp::Leaf(2.0, 3.0))
            ))
        );
    }

    #[test]
    fn new4_test() {
        let a = Lerp::new(&vec![1.0, 2.0, 3.0, 4.0]);
        assert_eq!(
            a,
            Rc::new(Lerp::Node(
                Rc::new(Lerp::Node(
                    Rc::new(Lerp::Leaf(1.0, 2.0)),
                    Rc::new(Lerp::Leaf(2.0, 3.0))
                )),
                Rc::new(Lerp::Node(
                    Rc::new(Lerp::Leaf(2.0, 3.0)),
                    Rc::new(Lerp::Leaf(3.0, 4.0))
                ))
            ))
        );
    }
}