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
108
109
110
111
mod valid_iter;
mod vec_map;

use tea_core::prelude::*;
pub use valid_iter::{Keep, MapValidBasic};
pub use vec_map::MapValidVec;
/// A trait for basic mapping operations on trusted length iterators.
///
/// This trait provides methods for common operations like absolute value and shifting,
/// which can be applied to iterators with a known length.
pub trait MapBasic: TrustedLen
where
    Self: Sized,
{
    /// Applies the absolute value function to each element in the iterator.
    ///
    /// # Examples
    ///
    /// ```
    /// use tea_core::prelude::*;
    /// use tea_map::MapBasic;
    ///
    /// let v = vec![-1, 2, -3, 4, -5];
    /// let result: Vec<_> = v.titer().abs().collect();
    /// assert_eq!(result, vec![1, 2, 3, 4, 5]);
    /// ```
    #[inline]
    fn abs(self) -> impl TrustedLen<Item = Self::Item>
    where
        Self::Item: Number,
    {
        self.map(|v| v.abs())
    }

    /// Shifts the elements of the iterator by `n` positions, filling in with the provided `value`.
    ///
    /// - If `n` is positive, shifts right and prepends `value`.
    /// - If `n` is negative, shifts left and appends `value`.
    /// - If `n` is zero, returns the original iterator.
    ///
    /// # Examples
    ///
    /// ```
    /// use tea_core::prelude::*;
    /// use tea_map::MapBasic;
    ///
    /// let v = vec![1, 2, 3, 4, 5];
    /// let result: Vec<_> = v.titer().shift(2, 0).collect();
    /// assert_eq!(result, vec![0, 0, 1, 2, 3]);
    ///
    /// let result: Vec<_> = v.titer().shift(-2, 0).collect();
    /// assert_eq!(result, vec![3, 4, 5, 0, 0]);
    /// ```
    fn shift<'a>(self, n: i32, value: Self::Item) -> Box<dyn TrustedLen<Item = Self::Item> + 'a>
    where
        Self::Item: Clone + 'a,
        Self: Sized + 'a,
    {
        let len = self.len();
        let n_abs = n.unsigned_abs() as usize;
        match n {
            n if n > 0 => Box::new(TrustIter::new(
                std::iter::repeat(value)
                    .take(n_abs)
                    .chain(self.take(len - n_abs)),
                len,
            )),
            n if n < 0 => Box::new(TrustIter::new(
                self.skip(n_abs).chain(std::iter::repeat(value).take(n_abs)),
                len,
            )),
            _ => Box::new(self),
        }
    }
}

impl<I: TrustedLen> MapBasic for I {}

#[cfg(test)]
mod test {
    use tea_core::testing::assert_vec1d_equal_numeric;

    use super::*;
    #[test]
    fn test_abs() {
        let v = vec![1, -2, 3, -4, 5];
        let res: Vec<_> = v.titer().abs().vabs().collect_trusted_vec1();
        assert_eq!(res, vec![1, 2, 3, 4, 5]);
        let v = vec![Some(1), Some(-2), None, Some(-4), Some(5)];
        let res: Vec<_> = v.titer().vabs().collect_trusted_vec1();
        assert_eq!(res, vec![Some(1), Some(2), None, Some(4), Some(5)]);
    }

    #[test]
    fn test_shift() {
        // test shift on empty vec
        let v: Vec<f64> = vec![];
        let res: Vec<_> = v.titer().vshift(2, None).collect_trusted_vec1();
        assert_eq!(res, vec![]);
        let v = vec![1., 2., 3., 4., 5.];
        let res: Vec<_> = v.titer().vshift(2, None).collect_trusted_vec1();
        assert_vec1d_equal_numeric(&res, &vec![f64::NAN, f64::NAN, 1., 2., 3.], None);
        let v = vec![1, 2, 3, 4, 5];
        let res: Vec<_> = v
            .titer()
            .vshift(-2, Some(0))
            .vshift(0, Some(0))
            .collect_trusted_to_vec();
        assert_eq!(res, vec![3, 4, 5, 0, 0]);
    }
}