tsmatch 0.2.0

Collection of utility functions to find pattern in time series data
Documentation
use super::Segment;

#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
enum Dir {
    Pos,
    Neg,
}

fn get_dir<T>(a: &T, b: &T, last_dir: Dir) -> Dir
where
    T: Ord,
{
    match a.cmp(b) {
        std::cmp::Ordering::Less => Dir::Neg,
        std::cmp::Ordering::Equal => last_dir,
        std::cmp::Ordering::Greater => Dir::Pos,
    }
}

pub fn vector_dir_change<'a, T>(data: &'a [T]) -> Vec<Segment<'a, T>>
where
    T: Ord,
{
    let mut out = vec![];
    if data.len() <= 2 {
        return vec![data];
    }

    let mut dir = get_dir(&data[1], &data[0], Dir::Pos);
    let mut pos = 0;

    for i in 2..data.len() {
        let c_dir = get_dir(&data[i], &data[i - 1], dir);
        if c_dir == dir {
            if i == data.len() - 1 {
                out.push(&data[pos..]);
            }
            continue;
        }

        out.push(&data[pos..i]);
        dir = c_dir;
        pos = i;
    }

    out
}

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

    #[test]
    fn test_segmentation_works() {
        let data = [
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
            0, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 3, 1,
            0, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
            6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 3, 3, 3, 1, 1, 1, 1, 0,
            6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
            6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 4, 2, 0,
        ];

        let expected = vec![
            [
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                1, 1,
            ]
            .as_slice(),
            [0].as_slice(),
            [
                5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
                5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
            ]
            .as_slice(),
            [4, 4, 4, 4, 4, 3, 1, 0].as_slice(),
            [
                6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
                6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
            ]
            .as_slice(),
            [5, 3, 3, 3, 1, 1, 1, 1, 0].as_slice(),
            [
                6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
                6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
            ]
            .as_slice(),
        ];

        for (a, b) in vector_dir_change(data.as_slice()).iter().zip(expected) {
            assert_eq!(*a, b);
        }
    }
}