1use crate::{Union, UnionResult};
9use std::cmp::Ordering;
10
11#[derive(Copy, Clone, Debug)]
15pub struct UnionBySize(usize);
16
17impl Union for UnionBySize {
18 #[inline]
19 fn union(left: UnionBySize, right: UnionBySize) -> UnionResult<UnionBySize> {
20 let lsize = left.size();
21 let rsize = right.size();
22 let result = UnionBySize(lsize + rsize);
23 if lsize >= rsize {
24 UnionResult::Left(result)
25 } else {
26 UnionResult::Right(result)
27 }
28 }
29}
30
31impl Default for UnionBySize {
32 #[inline]
33 fn default() -> UnionBySize {
34 UnionBySize(1)
35 }
36}
37
38impl UnionBySize {
39 #[inline]
41 pub fn size(&self) -> usize {
42 let UnionBySize(size) = *self;
43 size
44 }
45}
46
47#[derive(Copy, Clone, Debug, Default)]
52pub struct UnionByRank(u8);
53
54impl Union for UnionByRank {
55 #[inline]
56 fn union(left: UnionByRank, right: UnionByRank) -> UnionResult<UnionByRank> {
57 let lrank = left.rank();
58 let rrank = right.rank();
59 match lrank.cmp(&rrank) {
60 Ordering::Less => UnionResult::Right(right),
61 Ordering::Greater => UnionResult::Left(left),
62 Ordering::Equal => UnionResult::Left(UnionByRank(lrank + 1)),
63 }
64 }
65}
66
67impl UnionByRank {
68 #[inline]
70 pub fn rank(&self) -> u8 {
71 let UnionByRank(rank) = *self;
72 rank
73 }
74}
75
76#[derive(Copy, Clone, Debug)]
81pub struct UnionBySizeRank(usize, u8);
82
83impl Union for UnionBySizeRank {
84 #[inline]
85 fn union(left: UnionBySizeRank, right: UnionBySizeRank) -> UnionResult<UnionBySizeRank> {
86 let lsize = left.size();
87 let lrank = left.rank();
88 let rsize = right.size();
89 let rrank = right.rank();
90
91 let rank_cmp = lrank.cmp(&rrank);
92 let new_size = lsize + rsize;
93 let new_rank = match rank_cmp {
94 Ordering::Less => rrank,
95 Ordering::Greater => lrank,
96 Ordering::Equal => lrank + 1,
97 };
98
99 let result = UnionBySizeRank(new_size, new_rank);
100 match lsize.cmp(&rsize) {
101 Ordering::Less => UnionResult::Right(result),
102 Ordering::Greater => UnionResult::Left(result),
103 Ordering::Equal => match rank_cmp {
104 Ordering::Less => UnionResult::Right(result),
105 _ => UnionResult::Left(result),
106 },
107 }
108 }
109}
110
111impl Default for UnionBySizeRank {
112 #[inline]
113 fn default() -> UnionBySizeRank {
114 UnionBySizeRank(1, 0)
115 }
116}
117
118impl UnionBySizeRank {
119 #[inline]
121 pub fn size(&self) -> usize {
122 let UnionBySizeRank(size, _) = *self;
123 size
124 }
125
126 #[inline]
128 pub fn rank(&self) -> u8 {
129 let UnionBySizeRank(_, rank) = *self;
130 rank
131 }
132}
133
134#[derive(Copy, Clone, Debug)]
139pub struct UnionByRankSize(u8, usize);
140
141impl Union for UnionByRankSize {
142 #[inline]
143 fn union(left: UnionByRankSize, right: UnionByRankSize) -> UnionResult<UnionByRankSize> {
144 let lrank = left.rank();
145 let lsize = left.size();
146 let rrank = right.rank();
147 let rsize = right.size();
148
149 let rank_cmp = lrank.cmp(&rrank);
150 let new_size = lsize + rsize;
151 let new_rank = match rank_cmp {
152 Ordering::Less => rrank,
153 Ordering::Greater => lrank,
154 Ordering::Equal => lrank + 1,
155 };
156
157 let result = UnionByRankSize(new_rank, new_size);
158 match rank_cmp {
159 Ordering::Less => UnionResult::Right(result),
160 Ordering::Greater => UnionResult::Left(result),
161 Ordering::Equal => match lsize.cmp(&rsize) {
162 Ordering::Less => UnionResult::Right(result),
163 _ => UnionResult::Left(result),
164 },
165 }
166 }
167}
168
169impl Default for UnionByRankSize {
170 #[inline]
171 fn default() -> UnionByRankSize {
172 UnionByRankSize(1, 0)
173 }
174}
175
176impl UnionByRankSize {
177 #[inline]
179 pub fn rank(&self) -> u8 {
180 let UnionByRankSize(rank, _) = *self;
181 rank
182 }
183
184 #[inline]
186 pub fn size(&self) -> usize {
187 let UnionByRankSize(_, size) = *self;
188 size
189 }
190}