Skip to content

Commit 73422e8

Browse files
committed
hamming: Implement Hamming distance
1 parent 4876b97 commit 73422e8

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

src/hamming.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//! Hamming space.
2+
3+
use crate::distance::{Metric, Proximity};
4+
5+
use num_traits::PrimInt;
6+
7+
/// A point in Hamming space.
8+
///
9+
/// This wrapper equips any integer with the [Hamming distance] metric.
10+
///
11+
/// [Hamming distance]: https://en.wikipedia.org/wiki/Hamming_distance
12+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
13+
pub struct Hamming<T>(pub T);
14+
15+
impl<T> Hamming<T> {
16+
/// Wrap a point.
17+
pub fn new(point: T) -> Self {
18+
Self(point)
19+
}
20+
21+
/// Unwrap a point.
22+
pub fn into_inner(self) -> T {
23+
self.0
24+
}
25+
}
26+
27+
/// Compute the Hamming distance between two integers.
28+
pub fn hamming_distance<T: PrimInt>(x: T, y: T) -> i32 {
29+
(x ^ y).count_ones() as i32
30+
}
31+
32+
/// The hamming distance function.
33+
impl<T: PrimInt> Proximity for Hamming<T> {
34+
type Distance = i32;
35+
36+
fn distance(&self, other: &Self) -> Self::Distance {
37+
hamming_distance(self.0, other.0)
38+
}
39+
}
40+
41+
impl<T: PrimInt> Proximity<T> for Hamming<T> {
42+
type Distance = i32;
43+
44+
fn distance(&self, other: &T) -> Self::Distance {
45+
hamming_distance(self.0, *other)
46+
}
47+
}
48+
49+
impl<T: PrimInt> Proximity<Hamming<T>> for T {
50+
type Distance = i32;
51+
52+
fn distance(&self, other: &Hamming<T>) -> Self::Distance {
53+
hamming_distance(*self, other.0)
54+
}
55+
}
56+
57+
/// Hamming distance is a metric.
58+
impl<T: PrimInt> Metric for Hamming<T> {}
59+
60+
impl<T: PrimInt> Metric<T> for Hamming<T> {}
61+
62+
impl<T: PrimInt> Metric<Hamming<T>> for T {}
63+
64+
#[cfg(test)]
65+
mod tests {
66+
use super::*;
67+
68+
#[test]
69+
fn test_distance() {
70+
assert_eq!(hamming_distance(0, 0xFFFFFFFFu32), 32);
71+
72+
assert_eq!(Hamming(0xFFFFFFFFu32).distance(&Hamming(0xAAAAAAAAu32)), 16);
73+
assert_eq!(Hamming(0x55555555u32).distance(&0xAAAAAAAAu32), 32);
74+
assert_eq!(0xDEADBEEFu32.distance(&Hamming(0xACABACABu32)), 10);
75+
}
76+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ pub mod coords;
9595
pub mod distance;
9696
pub mod euclid;
9797
pub mod exhaustive;
98+
pub mod hamming;
9899
pub mod kd;
99100
pub mod taxi;
100101
pub mod vp;

0 commit comments

Comments
 (0)