Skip to main content

osom_lib_numbers/
iter_triangular.rs

1/// An iterator that generates triangular numbers, i.e.
2/// numbers of the form `n * (n + 1) / 2`.
3///
4/// Note that the iterator starts at 0 and not at 1.
5#[repr(C)]
6#[derive(Debug, Clone)]
7#[must_use]
8pub struct IterTriangular {
9    current: u32,
10    count: u32,
11}
12
13impl IterTriangular {
14    /// Creates a new iterator that generates `count` triangular numbers
15    /// as `u32`.
16    #[inline(always)]
17    pub const fn new(count: u32) -> Self {
18        Self { current: 0, count }
19    }
20
21    /// Returns the next triangular number.
22    #[must_use]
23    pub const fn next(&mut self) -> Option<u32> {
24        if self.current == self.count {
25            return None;
26        }
27
28        let result = self.current as u64;
29        let result = unsafe { result.unchecked_mul(result.unchecked_add(1)) } >> 1;
30
31        #[allow(clippy::cast_possible_truncation)]
32        let result = result as u32;
33
34        unsafe {
35            self.current = self.current.unchecked_add(1);
36        }
37
38        Some(result)
39    }
40}
41
42impl Iterator for IterTriangular {
43    type Item = u32;
44
45    #[inline(always)]
46    fn next(&mut self) -> Option<Self::Item> {
47        self.next()
48    }
49
50    #[inline(always)]
51    fn size_hint(&self) -> (usize, Option<usize>) {
52        #[allow(clippy::cast_possible_truncation)]
53        {
54            (self.count as usize, Some(self.count as usize))
55        }
56    }
57}