oxihuman_core/
gray_code.rs1#![allow(dead_code)]
4
5pub fn to_gray(n: u32) -> u32 {
6 n ^ (n >> 1)
7}
8
9pub fn from_gray(mut g: u32) -> u32 {
10 let mut mask = g >> 1;
11 while mask != 0 {
12 g ^= mask;
13 mask >>= 1;
14 }
15 g
16}
17
18pub fn gray_distance(a: u32, b: u32) -> u32 {
19 (a ^ b).count_ones()
20}
21
22pub fn gray_next(g: u32) -> u32 {
23 to_gray(from_gray(g).wrapping_add(1))
24}
25
26pub fn gray_prev(g: u32) -> u32 {
27 to_gray(from_gray(g).wrapping_sub(1))
28}
29
30pub fn gray_bits(g: u32) -> u32 {
31 g.count_ones()
32}
33
34#[cfg(test)]
35mod tests {
36 use super::*;
37
38 #[test]
39 fn gray_roundtrip() {
40 for n in 0u32..=15 {
42 assert_eq!(from_gray(to_gray(n)), n);
43 }
44 }
45
46 #[test]
47 fn consecutive_gray_differ_by_one_bit() {
48 for n in 0u32..=14 {
50 let diff = to_gray(n) ^ to_gray(n + 1);
51 assert_eq!(diff.count_ones(), 1);
52 }
53 }
54
55 #[test]
56 fn gray_distance_self() {
57 assert_eq!(gray_distance(0b101, 0b101), 0);
59 }
60
61 #[test]
62 fn gray_next_advances() {
63 let g = to_gray(5);
65 assert_eq!(gray_next(g), to_gray(6));
66 }
67
68 #[test]
69 fn gray_prev_decrements() {
70 let g = to_gray(5);
72 assert_eq!(gray_prev(g), to_gray(4));
73 }
74
75 #[test]
76 fn gray_bits_count() {
77 assert_eq!(gray_bits(0b1010), 2);
79 }
80
81 #[test]
82 fn to_gray_zero() {
83 assert_eq!(to_gray(0), 0);
85 }
86}