Skip to main content

osom_lib_numbers/iterators/
triangular.rs

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