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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//! A Cluster of `HpoSet` for linkage analysis.
//!
//! A cluster contains at least 2 `HpoSet`, but can also group other cluster.

/// A combination of (at least) 2 `HpoSet` for Dendogram clustering
///
/// This `struct` is created by the [`Linkage`](`crate::stats::Linkage`) struct and yielded
/// by the [`Linkage::into_cluster`](`crate::stats::Linkage::into_cluster`) and
/// [`Linkage::cluster`](`crate::stats::Linkage::cluster`) iterators
#[derive(Debug, Clone, Copy)]
pub struct Cluster {
    idx1: usize,
    idx2: usize,
    distance: f32,
    size: usize,
}

impl Cluster {
    /// Creates a new `Cluster`
    pub(super) fn new(idx1: usize, idx2: usize, distance: f32, size: usize) -> Self {
        Self {
            idx1,
            idx2,
            distance,
            size,
        }
    }

    /// Returns the index of the left hand side node
    pub fn lhs(&self) -> usize {
        self.idx1
    }

    /// Returns the index of the right hand side node
    pub fn rhs(&self) -> usize {
        self.idx2
    }

    /// Returns the distance of the two nodes
    pub fn distance(&self) -> f32 {
        self.distance
    }

    /// Returns the total number of child nodes
    #[allow(clippy::len_without_is_empty)]
    pub fn len(&self) -> usize {
        self.size
    }
}

#[derive(Debug, Default)]
pub(super) struct ClusterVec(Vec<Cluster>);

impl ClusterVec {
    pub(super) fn with_capacity(capacity: usize) -> Self {
        Self(Vec::with_capacity(capacity))
    }

    pub(super) fn push(&mut self, value: Cluster) {
        self.0.push(value);
    }

    pub(super) fn get(&self, index: usize) -> Option<&Cluster> {
        self.0.get(index)
    }

    pub(super) fn iter(&self) -> Iter<'_> {
        self.into_iter()
    }
}

impl IntoIterator for ClusterVec {
    type Item = Cluster;
    type IntoIter = IntoIter;
    fn into_iter(self) -> Self::IntoIter {
        IntoIter::new(self.0.into_iter())
    }
}

impl<'a> IntoIterator for &'a ClusterVec {
    type Item = &'a Cluster;
    type IntoIter = Iter<'a>;
    fn into_iter(self) -> Self::IntoIter {
        Iter::new(self.0.iter())
    }
}

/// Iterates [`Cluster`] references
///
/// This `struct` is yielded by the [`Linkage::cluster`](`crate::stats::Linkage::cluster`) method
pub struct Iter<'a> {
    iter: std::slice::Iter<'a, Cluster>,
}

impl<'a> Iter<'a> {
    fn new(iter: std::slice::Iter<'a, Cluster>) -> Self {
        Self { iter }
    }
}

impl<'a> Iterator for Iter<'a> {
    type Item = &'a Cluster;

    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next()
    }
}

impl DoubleEndedIterator for Iter<'_> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iter.next_back()
    }
}

impl ExactSizeIterator for Iter<'_> {
    fn len(&self) -> usize {
        self.iter.len()
    }
}

/// Iterates [`Cluster`]
///
/// This `struct` is yielded by the [`Linkage::into_cluster`](`crate::stats::Linkage::into_cluster`) method
#[derive(Debug)]
pub struct IntoIter {
    iter: std::vec::IntoIter<Cluster>,
}

impl IntoIter {
    fn new(iter: std::vec::IntoIter<Cluster>) -> Self {
        Self { iter }
    }
}

impl Iterator for IntoIter {
    type Item = Cluster;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl DoubleEndedIterator for IntoIter {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iter.next_back()
    }
}

impl ExactSizeIterator for IntoIter {
    fn len(&self) -> usize {
        self.iter.len()
    }
}