pikkr 0.0.6

A Rust library providing the Pikkr core APIs
Documentation
//! Bit manipulations.
//!
//! This module provides bit manipulations.

/// Removes the rightmost 1 in bits.
///
/// ## Manipulation
/// r(x) = x & (x - 1)
///
/// ## Example
/// x = 11101000(2)
///
/// r(x) = 11100000(2)
#[inline]
pub fn r(x: u64) -> u64 {
    x & x.wrapping_sub(1)
}

/// Extracts the rightmost 1 in bits.
///
/// ## Manipulation
/// e(x) = x & !x
///
/// ## Example
/// x = 11101000(2)
///
/// e(x) = 00001000(2)
#[inline]
pub fn e(x: u64) -> u64 {
    x & x.wrapping_neg()
}

/// Extracts the rightmost 1 in bits and smear it to the right.
///
/// ## Manipulation
/// s(x) = x ^ (x - 1)
///
/// ## Example
/// x = 11101000(2)
///
/// s(x) = 00001111(2)
#[inline]
pub fn s(x: u64) -> u64 {
    x ^ x.saturating_sub(1)
}

#[cfg(test)]
mod tests {
    use super::*;
    use test;

    #[test]
    fn test_r() {
        struct TestCase {
            x: u64,
            want: u64,
        }

        let test_cases = vec![
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000010u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000000_00000001_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000001_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000001_00000000_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000001_00000000_00000000_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000001_00000000_00000000_00000000_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000001_00000000_00000000_00000000_00000000_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000001_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000011u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000010u64,
            },
            TestCase {
                x:    0b10000000_00100000_00000000_00000000_00000000_00000000_00000100_00000000u64,
                want: 0b10000000_00100000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
             TestCase {
                x:    0b00000000_00010000_00110010_00000000_00000000_00001100_00000000_00000000u64,
                want: 0b00000000_00010000_00110010_00000000_00000000_00001000_00000000_00000000u64,
            },
             TestCase {
                x:    0b11100000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
                want: 0b11000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
             TestCase {
                x:    0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111u64,
                want: 0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111110u64,
            },
        ];

        for test_case in test_cases {
            assert_eq!(test_case.want, r(test_case.x));
        }
    }

    #[test]
    fn test_e() {
        struct TestCase {
            x: u64,
            want: u64,
        }

        let test_cases = vec![
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000010u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000010u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000000_00000001_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000001_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000001_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000001_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000001_00000000_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000001_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000001_00000000_00000000_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000001_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000001_00000000_00000000_00000000_00000000_00000000u64,
                want: 0b00000000_00000000_00000001_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000001_00000000_00000000_00000000_00000000_00000000_00000000u64,
                want: 0b00000000_00000001_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000001_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
                want: 0b00000001_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000011u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001u64,
            },
            TestCase {
                x:    0b10000000_00100000_00000000_00000000_00000000_00000000_00000100_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000100_00000000u64,
            },
            TestCase {
                x:    0b00000000_00010000_00110010_00000000_00000000_00001100_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000100_00000000_00000000u64,
            },
            TestCase {
                x:    0b11100000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
                want: 0b00100000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001u64,
            },
        ];

        for test_case in test_cases {
            assert_eq!(test_case.want, e(test_case.x));
        }
    }

    #[test]
    fn test_s() {
        struct TestCase {
            x: u64,
            want: u64,
        }

        let test_cases = vec![
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000010u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000011u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000000_00000001_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000001_11111111u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000001_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000001_11111111_11111111u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000001_00000000_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000001_11111111_11111111_11111111u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000001_00000000_00000000_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000001_11111111_11111111_11111111_11111111u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000001_00000000_00000000_00000000_00000000_00000000u64,
                want: 0b00000000_00000000_00000001_11111111_11111111_11111111_11111111_11111111u64,
            },
            TestCase {
                x:    0b00000000_00000001_00000000_00000000_00000000_00000000_00000000_00000000u64,
                want: 0b00000000_00000001_11111111_11111111_11111111_11111111_11111111_11111111u64,
            },
            TestCase {
                x:    0b00000001_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
                want: 0b00000001_11111111_11111111_11111111_11111111_11111111_11111111_11111111u64,
            },
            TestCase {
                x:    0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000011u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001u64,
            },
            TestCase {
                x:    0b10000000_00100000_00000000_00000000_00000000_00000000_00000100_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000111_11111111u64,
            },
            TestCase {
                x:    0b00000000_00010000_00110010_00000000_00000000_00001100_00000000_00000000u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000111_11111111_11111111u64,
            },
            TestCase {
                x:    0b11100000_00000000_00000000_00000000_00000000_00000000_00000000_00000000u64,
                want: 0b00111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111u64,
            },
            TestCase {
                x:    0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111u64,
                want: 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001u64,
            },
        ];

        for test_case in test_cases {
            println!("{:b} {:b} {:b}", test_case.x, test_case.x.wrapping_sub(1), s(test_case.x));
            assert_eq!(test_case.want, s(test_case.x));
        }
    }

    #[bench]
    fn bench_r(b: &mut test::Bencher) {
        b.iter(|| {
            let mut u = 0u64;
            for _ in 0..500 {
                u = r(0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111u64);
            }
            u
        });
    }

    #[bench]
    fn bench_e(b: &mut test::Bencher) {
        b.iter(|| {
            let mut u = 0u64;
            for _ in 0..500 {
                u = e(0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111u64);
            }
            u
        });
    }

    #[bench]
    fn bench_s(b: &mut test::Bencher) {
        b.iter(|| {
            let mut u = 0u64;
            for _ in 0..500 {
                u = s(0b11111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111u64);
            }
            u
        });
    }
}