toolbox_rs/
enumerative_source_coding.rs

1use crate::math::choose;
2
3/// Implementation of Cover's algorithm to enumerate of sequences of weight w, cf.
4/// "Enumerative Source Encoding". Thomas M. Cover.
5/// Appears in IEEE Transactions on Information Theory. Vol 19, Issue: 1, Jan 1973
6///
7/// The implementation corresponds to Section "Example 2 - Enumeration of Sequences of Weight w".
8///
9/// # Examples
10///
11/// ```
12/// use toolbox_rs::enumerative_source_coding::decode_u64;
13///
14/// // 0th number with 3 bits set in a 64 bit number
15/// assert_eq!(decode_u64(3, 0), 0b000_0111);    
16/// ```
17pub fn decode_u64(mut ones: u64, mut ordinal: u64) -> u64 {
18    debug_assert!(ordinal < choose(64, ones));
19    let mut result = 0;
20    for bit in (0..64).rev() {
21        let n_ck = choose(bit, ones);
22        if ordinal >= n_ck {
23            ordinal -= n_ck;
24            result |= 1 << bit;
25            ones -= 1;
26        }
27    }
28    result
29}
30
31#[cfg(test)]
32mod tests {
33    use crate::enumerative_source_coding::decode_u64;
34
35    #[test]
36    fn paper_examples() {
37        // 0th number with 3 bits set
38        assert_eq!(decode_u64(3, 0), 0b0000_0111);
39        // 1st number with 3 bits set
40        assert_eq!(decode_u64(3, 1), 0b0000_1011);
41        // 21st number with 3 bits set
42        assert_eq!(decode_u64(3, 21), 0b0100_0101);
43        // 34th number with 3 bits set
44        assert_eq!(decode_u64(3, 34), 0b0111_0000);
45        // 41663th (last) number with 3 bits set
46        assert_eq!(
47            decode_u64(3, 41663),
48            0b1110_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000
49        );
50    }
51}