competitive/data_structure/
fibonacci_hash.rs1use std::{
2 collections::{HashMap, HashSet},
3 convert::TryInto,
4 hash::{BuildHasherDefault, Hasher},
5};
6
7#[cfg(target_pointer_width = "32")]
8pub type FibonacciHasher = FibonacciHasheru32;
9#[cfg(not(target_pointer_width = "32"))]
10pub type FibonacciHasher = FibonacciHasheru64;
11pub type FibHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FibonacciHasher>>;
12pub type FibHashSet<V> = HashSet<V, BuildHasherDefault<FibonacciHasher>>;
13
14#[derive(Debug, Default)]
15pub struct FibonacciHasheru32 {
16 hash: u32,
17}
18impl FibonacciHasheru32 {
19 const A: u32 = 2654435769;
20 const B: u32 = 5;
21 fn push(&mut self, x: u32) {
22 self.hash = (self.hash.rotate_right(Self::B) ^ x).wrapping_mul(Self::A);
23 }
24}
25impl Hasher for FibonacciHasheru32 {
26 fn finish(&self) -> u64 {
27 self.hash as u64
28 }
29 fn write(&mut self, mut bytes: &[u8]) {
30 if bytes.len() % 4 >= 2 {
31 self.push(u16::from_ne_bytes(bytes[..2].try_into().unwrap()) as u32);
32 bytes = &bytes[2..];
33 }
34 if bytes.len() % 2 >= 1 {
35 self.push(u16::from_ne_bytes(bytes[..1].try_into().unwrap()) as u32);
36 bytes = &bytes[1..];
37 }
38 for chunk in bytes.chunks(4) {
39 self.push(u32::from_ne_bytes(chunk.try_into().unwrap()));
40 }
41 }
42 fn write_u8(&mut self, i: u8) {
43 self.push(i as u32)
44 }
45 fn write_u16(&mut self, i: u16) {
46 self.push(i as u32)
47 }
48 fn write_u32(&mut self, i: u32) {
49 self.push(i)
50 }
51 fn write_u64(&mut self, i: u64) {
52 self.push(i as u32);
53 self.push((i >> 32) as u32);
54 }
55 fn write_u128(&mut self, i: u128) {
56 self.push(i as u32);
57 self.push((i >> 32) as u32);
58 self.push((i >> 64) as u32);
59 self.push((i >> 96) as u32);
60 }
61 #[cfg(target_pointer_width = "32")]
62 fn write_usize(&mut self, i: usize) {
63 self.write_u32(i as u32)
64 }
65 #[cfg(target_pointer_width = "64")]
66 fn write_usize(&mut self, i: usize) {
67 self.write_u64(i as u64)
68 }
69 fn write_i8(&mut self, i: i8) {
70 self.write_u8(i as u8)
71 }
72 fn write_i16(&mut self, i: i16) {
73 self.write_u16(i as u16)
74 }
75 fn write_i32(&mut self, i: i32) {
76 self.write_u32(i as u32)
77 }
78 fn write_i64(&mut self, i: i64) {
79 self.write_u64(i as u64)
80 }
81 fn write_i128(&mut self, i: i128) {
82 self.write_u128(i as u128)
83 }
84 fn write_isize(&mut self, i: isize) {
85 self.write_usize(i as usize)
86 }
87}
88
89#[derive(Debug, Default)]
90pub struct FibonacciHasheru64 {
91 hash: u64,
92}
93impl FibonacciHasheru64 {
94 const A: u64 = 11400714819323198485;
95 const B: u32 = 5;
96 fn push(&mut self, x: u64) {
97 self.hash = (self.hash.rotate_right(Self::B) ^ x).wrapping_mul(Self::A);
98 }
99}
100impl Hasher for FibonacciHasheru64 {
101 fn finish(&self) -> u64 {
102 self.hash
103 }
104 fn write(&mut self, mut bytes: &[u8]) {
105 if bytes.len() % 8 >= 4 {
106 self.push(u16::from_ne_bytes(bytes[..4].try_into().unwrap()) as u64);
107 bytes = &bytes[4..];
108 }
109 if bytes.len() % 4 >= 2 {
110 self.push(u16::from_ne_bytes(bytes[..2].try_into().unwrap()) as u64);
111 bytes = &bytes[2..];
112 }
113 if bytes.len() % 2 >= 1 {
114 self.push(u16::from_ne_bytes(bytes[..1].try_into().unwrap()) as u64);
115 bytes = &bytes[1..];
116 }
117 for chunk in bytes.chunks(8) {
118 self.push(u64::from_ne_bytes(chunk.try_into().unwrap()));
119 }
120 }
121 fn write_u8(&mut self, i: u8) {
122 self.push(i as u64)
123 }
124 fn write_u16(&mut self, i: u16) {
125 self.push(i as u64)
126 }
127 fn write_u32(&mut self, i: u32) {
128 self.push(i as u64)
129 }
130 fn write_u64(&mut self, i: u64) {
131 self.push(i);
132 }
133 fn write_u128(&mut self, i: u128) {
134 self.push(i as u64);
135 self.push((i >> 64) as u64);
136 }
137 fn write_usize(&mut self, i: usize) {
138 self.write_u64(i as u64)
139 }
140 fn write_i8(&mut self, i: i8) {
141 self.write_u8(i as u8)
142 }
143 fn write_i16(&mut self, i: i16) {
144 self.write_u16(i as u16)
145 }
146 fn write_i32(&mut self, i: i32) {
147 self.write_u32(i as u32)
148 }
149 fn write_i64(&mut self, i: i64) {
150 self.write_u64(i as u64)
151 }
152 fn write_i128(&mut self, i: i128) {
153 self.write_u128(i as u128)
154 }
155 fn write_isize(&mut self, i: isize) {
156 self.write_usize(i as usize)
157 }
158}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163 use crate::tools::Xorshift;
164 use std::collections::BTreeSet;
165
166 #[test]
167 fn test_hash_slice() {
168 const Q: usize = 50_000;
169
170 let mut rng = Xorshift::default();
171 let mut fh = FibHashSet::default();
172 let mut rh = HashSet::new();
173 for _ in 0..Q {
174 let n = rng.random(0..20);
175 let a: Vec<_> = rng.random_iter(0u64..).take(n).collect();
176 fh.insert(a.to_vec());
177 rh.insert(a.to_vec());
178 }
179
180 let fh = fh.into_iter().collect::<BTreeSet<_>>();
181 let rh = rh.into_iter().collect::<BTreeSet<_>>();
182 assert_eq!(fh, rh);
183 }
184}