1use crate::{traits::*, hash_trie::HashTrie, *};
2use alloc::fmt::Debug;
3
4#[derive(Clone, Debug)]
67#[must_use]
68pub struct HashTrieSet <H: Hashword, F: Flagword<H>, K: Key, M: HasherBv<H, K>> where <F as core::convert::TryFrom<<H as core::ops::BitAnd>::Output>>::Error: core::fmt::Debug {
69 set: HashTrie<H, F, K, (), M>,
70}
71
72impl <H: Hashword, F: Flagword<H>, K: Key, M: HasherBv<H, K>> HashTrieSet<H, F, K, M> where <F as core::convert::TryFrom<<H as core::ops::BitAnd>::Output>>::Error: core::fmt::Debug {
73 pub fn new() -> Self {
75 Self {
76 set: HashTrie::new()
77 }
78 }
79
80 pub fn size(&self) -> usize {
82 self.set.size()
83 }
84
85 pub fn find<'a, L: Key + HashLike<K>>(&'a self, key: &L) -> Result<&'a K, HashTrieError> where K: PartialEq<L>, M: HasherBv<H, L> {
87 self.set.find(key).map(|(key, _value)| key)
88 }
89
90 pub fn insert<'a, L: Key + HashLike<K> + Into<K>>(&'a self, key: L, replace: bool) -> Result<(Self, *const K, Option<&'a K>), &'a K>
93 where
94 K: HashLike<L>,
95 K: PartialEq<L>,
96 M: HasherBv<H, L>
97 {
98 self.set.insert(key, (), replace).map(|(set, key, _value, prev)| (Self {set}, key, prev.map(|(k, _v)| k))).map_err(|(key, _value)| key)
99 }
100
101 pub fn remove<'a, L: Key + HashLike<K>>(&'a self, key: &L) -> Result<(Self, &'a K), HashTrieError> where K: PartialEq<L>, M: HasherBv<H, L> {
103 self.set.remove(key).map(|(set, key, _value)| (Self {set}, key))
104 }
105
106 pub fn visit<Op: Clone>(&self, op: Op) where Op: Fn(&K) {
108 self.set.visit(|key, _value| op(key));
109 }
110
111 pub fn transform<ReduceT, ReduceOp, Op>
113 (&self, reduce_op: ReduceOp, op: Op) -> (Self, ReduceT)
114 where
115 Self: Sized,
116 ReduceT: Default,
117 ReduceOp: Fn(&ReduceT, &ReduceT) -> ReduceT + Clone,
118 Op: Fn(&K) -> SetTransformResult<ReduceT> + Clone,
119 {
120 let (set, reduced) = self.set.transform(reduce_op, |key, _value| match op(key) {
121 SetTransformResult::Unchanged(reduced) => MapTransformResult::Unchanged(reduced),
122 SetTransformResult::Removed(reduced) => MapTransformResult::Removed(reduced),
123 });
124 (Self{set}, reduced)
125 }
126
127 pub unsafe fn transmute<S: Key + HashLike<S>, ReduceT, ReduceOp, Op>
129 (&self, reduce_op: ReduceOp, op: Op) -> (HashTrieSet<H, F, S, M>, ReduceT)
130 where
131 Self: Sized,
132 ReduceT: Default,
133 ReduceOp: Fn(&ReduceT, &ReduceT) -> ReduceT + Clone,
134 Op: Fn(&K) -> SetTransmuteResult<S, ReduceT> + Clone,
135 K: HashLike<S>,
136 K: PartialEq<S>,
137 M: HasherBv<H, S>,
138 {
139 let (set, reduced) = self.set.transmute(reduce_op, |key, _value| match op(key) {
140 SetTransmuteResult::Transmuted(key, reduced) => MapTransmuteResult::Transmuted(key, (), reduced),
141 SetTransmuteResult::Removed(reduced) => MapTransmuteResult::Removed(reduced),
142 });
143 (HashTrieSet{set}, reduced)
144 }
145
146 pub fn transform_with_transformed<ReduceT, ReduceOp, BothOp, LeftOp, RightOp>
148 (&self, right: &Self, reduce_op: ReduceOp, both_op: BothOp, left_op: LeftOp, right_op: RightOp) -> (Self, ReduceT)
149 where
150 Self: Sized,
151 ReduceT: Default,
152 ReduceOp: Fn(&ReduceT, &ReduceT) -> ReduceT + Clone,
153 BothOp: Fn(&K, &K) -> SetJointTransformResult<ReduceT> + Clone,
154 LeftOp: Fn(&K) -> SetTransformResult<ReduceT> + Clone,
155 RightOp: Fn(&K) -> SetTransformResult<ReduceT> + Clone,
156 {
157 let (set, reduced) = self.set.transform_with_transformed(&right.set, reduce_op,
158 |l,_,r,_| both_op(l, r).into(),
159 |l,_| left_op(l).into(),
160 |r,_| right_op(r).into());
161 (HashTrieSet{set}, reduced)
162 }
163
164 pub unsafe fn transform_with_transmuted<L: Key + HashLike<K>, ReduceT, ReduceOp, BothOp, LeftOp, RightOp>
166 (&self, right: &HashTrieSet<H, F, L, M>, reduce_op: ReduceOp, both_op: BothOp, left_op: LeftOp, right_op: RightOp) -> (Self, ReduceT)
167 where
168 Self: Sized,
169 ReduceT: Default,
170 ReduceOp: Fn(&ReduceT, &ReduceT) -> ReduceT + Clone,
171 BothOp: Fn(&K, &L) -> SetTransformResult<ReduceT> + Clone,
172 LeftOp: Fn(&K) -> SetTransformResult<ReduceT> + Clone,
173 RightOp: Fn(&L) -> SetTransmuteResult<K, ReduceT> + Clone,
174 K: HashLike<L>,
175 K: PartialEq<L>,
176 L: HashLike<K>,
177 L: PartialEq<K>,
178 M: HasherBv<H, L>,
179 {
180 let (set, reduced) = self.set.transform_with_transmuted(&right.set, reduce_op,
181 |l,_,r,_| both_op(l, r).into(),
182 |l,_| left_op(l).into(),
183 |r,_| match right_op(r) {
184 SetTransmuteResult::Transmuted(key, reduced) => MapTransmuteResult::Transmuted(key, (), reduced),
185 SetTransmuteResult::Removed(reduced) => MapTransmuteResult::Removed(reduced),
186 });
187 (HashTrieSet{set}, reduced)
188 }
189
190 pub unsafe fn transmute_with_transformed<L: Key + HashLike<K>, ReduceT, ReduceOp, BothOp, LeftOp, RightOp>
192 (&self, right: &HashTrieSet<H, F, L, M>, reduce_op: ReduceOp, both_op: BothOp, left_op: LeftOp, right_op: RightOp) -> (HashTrieSet<H, F, L, M>, ReduceT)
193 where
194 Self: Sized,
195 ReduceT: Default,
196 ReduceOp: Fn(&ReduceT, &ReduceT) -> ReduceT + Clone,
197 BothOp: Fn(&K, &L) -> SetTransformResult<ReduceT> + Clone,
198 LeftOp: Fn(&K) -> SetTransmuteResult<L, ReduceT> + Clone,
199 RightOp: Fn(&L) -> SetTransformResult<ReduceT> + Clone,
200 K: HashLike<L>,
201 K: PartialEq<L>,
202 L: HashLike<K>,
203 L: PartialEq<K>,
204 M: HasherBv<H, L>,
205 {
206 let (set, reduced) = self.set.transmute_with_transformed(&right.set, reduce_op,
207 |l,_,r,_| both_op(l, r).into(),
208 |l,_| match left_op(l) {
209 SetTransmuteResult::Transmuted(key, reduced) => MapTransmuteResult::Transmuted(key, (), reduced),
210 SetTransmuteResult::Removed(reduced) => MapTransmuteResult::Removed(reduced),
211 },
212 |r,_| right_op(r).into());
213 (HashTrieSet{set}, reduced)
214 }
215
216 pub unsafe fn transmute_with_transmuted<L: Key + HashLike<K>, S: Key + HashLike<K>, ReduceT, ReduceOp, BothOp, LeftOp, RightOp>
218 (&self, right: &HashTrieSet<H, F, L, M>, reduce_op: ReduceOp, both_op: BothOp, left_op: LeftOp, right_op: RightOp) -> (HashTrieSet<H, F, S, M>, ReduceT)
219 where
220 Self: Sized,
221 ReduceT: Default,
222 ReduceOp: Fn(&ReduceT, &ReduceT) -> ReduceT + Clone,
223 BothOp: Fn(&K, &L) -> SetTransmuteResult<S, ReduceT> + Clone,
224 LeftOp: Fn(&K) -> SetTransmuteResult<S, ReduceT> + Clone,
225 RightOp: Fn(&L) -> SetTransmuteResult<S, ReduceT> + Clone,
226 K: HashLike<L>,
227 K: PartialEq<L>,
228 K: HashLike<S>,
229 K: PartialEq<S>,
230 L: HashLike<K>,
231 L: PartialEq<K>,
232 L: HashLike<S>,
233 L: PartialEq<S>,
234 M: HasherBv<H, L>,
235 M: HasherBv<H, S>,
236 {
237 let (set, reduced) = self.set.transmute_with_transmuted(&right.set, reduce_op, |l,_,r,_| match both_op(l, r) {
238 SetTransmuteResult::Transmuted(key, reduced) => MapTransmuteResult::Transmuted(key, (), reduced),
239 SetTransmuteResult::Removed(reduced) => MapTransmuteResult::Removed(reduced),
240 }, |l,_| match left_op(l) {
241 SetTransmuteResult::Transmuted(key, reduced) => MapTransmuteResult::Transmuted(key, (), reduced),
242 SetTransmuteResult::Removed(reduced) => MapTransmuteResult::Removed(reduced),
243 }, |r,_| match right_op(r) {
244 SetTransmuteResult::Transmuted(key, reduced) => MapTransmuteResult::Transmuted(key, (), reduced),
245 SetTransmuteResult::Removed(reduced) => MapTransmuteResult::Removed(reduced),
246 });
247 (HashTrieSet{set}, reduced)
248 }
249
250}
251
252impl <H: Hashword, F: Flagword<H>, K: Key, M: HasherBv<H, K>> Default for HashTrieSet<H, F, K, M> where <F as core::convert::TryFrom<<H as core::ops::BitAnd>::Output>>::Error: core::fmt::Debug {
253 fn default() -> Self {
254 Self::new()
255 }
256}
257
258impl <H: Hashword, F: Flagword<H>, K: Key, M: HasherBv<H, K>> Eq for HashTrieSet<H, F, K, M> where <F as core::convert::TryFrom<<H as core::ops::BitAnd>::Output>>::Error: core::fmt::Debug {}
259
260impl <H: Hashword, F: Flagword<H>, K: Key, M: HasherBv<H, K>> PartialEq for HashTrieSet<H, F, K, M> where <F as core::convert::TryFrom<<H as core::ops::BitAnd>::Output>>::Error: core::fmt::Debug {
261 fn eq(&self, other: &Self) -> bool {
262 self.set == other.set
263 }
264}
265
266#[cfg(test)]
267mod tests {
268 use crate::*;
269 use rand::Rng;
270
271 #[test]
272 fn set_transform() {
273 let mut set = DefaultHashTrieSet::<i32>::new();
274
275 for i in 1..101 {
276 set = set.insert(i, false).unwrap().0;
277 }
278
279 let removed = set.transform(|_,_| (), |_| SetTransformResult::Removed(()));
280 let summed = set.transform(|&l,&r| l + r, |&k| SetTransformResult::Removed(k));
281
282 assert_eq!(removed.0.size(), 0);
283 assert_eq!(summed.1, 5050);
284 }
285
286 #[test]
287 fn set_transmute() {
288 let mut set = DefaultHashTrieSet::<i32>::new();
289
290 for i in 1..101 {
291 set = set.insert(i, false).unwrap().0;
292 }
293
294 let removed = unsafe { set.transmute(|_,_| (), |_| SetTransmuteResult::Removed(())) };
295 let summed = unsafe { set.transmute(|&l,&r| l + r, |&k| SetTransmuteResult::Removed(k)) };
296
297 assert_eq!(removed.0.size(), 0);
298 assert_eq!(summed.1, 5050);
299 }
300
301 #[test]
302 fn set_joint_transformations() {
303 let mut seta = DefaultHashTrieSet::<i32>::new();
304 let mut setb = DefaultHashTrieSet::<i32>::new();
305
306 let mut rng = rand::thread_rng();
307 let a = (0..25000).map(|_| rng.gen_range(0..100000)).collect::<Vec<i32>>();
308 let b = (0..25000).map(|_| rng.gen_range(0..100000)).collect::<Vec<i32>>();
309 for i in a {
310 seta = seta.insert(i, true).unwrap().0;
311 }
312 for i in b {
313 setb = setb.insert(i, true).unwrap().0;
314 }
315
316 let ff = seta.transform_with_transformed(&setb, |l,r| -> i32 {l.wrapping_add(*r)},
317 |l,r| SetJointTransformResult::Removed(l.wrapping_mul(*r)), |l| SetTransformResult::Unchanged(*l), |r| SetTransformResult::Unchanged(*r));
318 let fm = unsafe { seta.transform_with_transmuted(&setb, |l,r| -> i32 {l.wrapping_add(*r)},
319 |l,r| SetTransformResult::Removed(l.wrapping_mul(*r)), |l| SetTransformResult::Unchanged(*l), |r| SetTransmuteResult::Transmuted(*r, *r)) };
320 let mf = unsafe { seta.transmute_with_transformed(&setb, |l,r| -> i32 {l.wrapping_add(*r)},
321 |l,r| SetTransformResult::Removed(l.wrapping_mul(*r)), |l| SetTransmuteResult::Transmuted(*l, *l), |r| SetTransformResult::Unchanged(*r)) };
322 let mm = unsafe { seta.transmute_with_transmuted(&setb, |l,r| -> i32 {l.wrapping_add(*r)},
323 |l,r| SetTransmuteResult::Removed(l.wrapping_mul(*r)), |l| SetTransmuteResult::Transmuted(*l, *l), |r| SetTransmuteResult::Transmuted(*r, *r)) };
324
325 assert_eq!(ff.1, fm.1);
326 assert_eq!(ff.1, mf.1);
327 assert_eq!(ff.1, mm.1);
328
329 let ffx = ff.0.transform(|l,r| -> i32 {l.wrapping_add(*r)}, |k| SetTransformResult::Removed(*k));
330 let fmx = fm.0.transform(|l,r| -> i32 {l.wrapping_add(*r)}, |k| SetTransformResult::Removed(*k));
331 let mfx = mf.0.transform(|l,r| -> i32 {l.wrapping_add(*r)}, |k| SetTransformResult::Removed(*k));
332 let mmx = mm.0.transform(|l,r| -> i32 {l.wrapping_add(*r)}, |k| SetTransformResult::Removed(*k));
333
334 assert_eq!(ffx.1, fmx.1);
335 assert_eq!(ffx.1, mfx.1);
336 assert_eq!(ffx.1, mmx.1);
337 }
338
339}