| 57 | /// for the remainder. ~4x faster than byte-level for vectors ≥64 dims. |
| 58 | #[inline] |
| 59 | pub fn hamming_distance_fast(a: &[u8], b: &[u8]) -> u32 { |
| 60 | debug_assert_eq!(a.len(), b.len()); |
| 61 | let mut dist = 0u32; |
| 62 | let chunks = a.len() / 8; |
| 63 | let remainder = a.len() % 8; |
| 64 | |
| 65 | // Process u64 chunks (slice is guaranteed to be 8 bytes by loop bounds). |
| 66 | for i in 0..chunks { |
| 67 | let offset = i * 8; |
| 68 | let mut a_buf = [0u8; 8]; |
| 69 | let mut b_buf = [0u8; 8]; |
| 70 | a_buf.copy_from_slice(&a[offset..offset + 8]); |
| 71 | b_buf.copy_from_slice(&b[offset..offset + 8]); |
| 72 | dist += (u64::from_le_bytes(a_buf) ^ u64::from_le_bytes(b_buf)).count_ones(); |
| 73 | } |
| 74 | |
| 75 | // Process remaining bytes. |
| 76 | let start = chunks * 8; |
| 77 | for i in 0..remainder { |
| 78 | dist += (a[start + i] ^ b[start + i]).count_ones(); |
| 79 | } |
| 80 | |
| 81 | dist |
| 82 | } |
| 83 | |
| 84 | /// Binary vector size in bytes for a given dimensionality. |
| 85 | pub fn binary_size(dim: usize) -> usize { |