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
use super::{Complex, Poly, Scalar};

pub trait Get<I, T: Scalar> {
    fn get(&self, idx: I) -> Option<Complex<T>>;
}

impl<T: Scalar> Get<usize, T> for Poly<T> {
    fn get(&self, idx: usize) -> Option<Complex<T>> {
        debug_assert!(self.is_normalized());

        if idx >= self.len_raw() {
            return None;
        }

        Some(self.0[idx].clone())
    }
}

impl<T: Scalar> Get<isize, T> for Poly<T> {
    #[allow(clippy::cast_possible_wrap)]
    #[allow(clippy::cast_sign_loss)]
    fn get(&self, idx: isize) -> Option<Complex<T>> {
        if idx >= 0 {
            return self.get(idx as usize);
        }

        // find the index from the end
        let idx = self.len_raw() as isize + idx;
        // if negative, it means index was out of range
        if idx < 0 {
            return None;
        }

        self.get(idx as usize)
    }
}

#[cfg(test)]
mod test {
    use num::{complex::Complex64, One, Zero};
    use numeric_constant_traits::{Three, Two};

    use super::*;

    #[test]
    fn test_get_isize() {
        let p = poly![0.0, 1.0, 2.0, 3.0];
        assert_eq!(p.get(0isize).unwrap(), Complex64::zero());
        assert_eq!(p.get(1isize).unwrap(), Complex64::one());
        assert_eq!(p.get(-1isize).unwrap(), Complex64::three());
        assert_eq!(p.get(-2isize).unwrap(), Complex64::two());
        assert_eq!(p.get(-4isize).unwrap(), Complex64::zero());

        // out of bounds
        assert!(p.get(4isize).is_none());
        assert!(p.get(-5isize).is_none())
    }

    #[test]
    fn test_get_usize() {
        let p = poly![0.0, 1.0, 2.0, 3.0];
        assert_eq!(p.get(0usize).unwrap(), Complex64::zero());
        assert_eq!(p.get(1usize).unwrap(), Complex64::one());
        assert_eq!(p.get(3usize).unwrap(), Complex64::three());

        // out of bounds
        assert!(p.get(4usize).is_none());
    }
}