secded 1.1.0

Single Error Correction, Double Error Detection Codes for Everyone
Documentation
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

pub trait Bitwise {
    type Output;
    fn count(&self) -> Self::Output;
    fn parity(&self) -> Self::Output;
}

impl Bitwise for u128 {
    type Output = u128;
    fn count(&self) -> u128 {
        let mut count = 0;
        let mut copy = *self;
        while copy != 0 {
            count += copy & 1;
            copy >>= 1;
        }
        count
    }

    fn parity(&self) -> u128 {
        let mut result = *self;
        result ^= result >> 64;
        result ^= result >> 32;
        result ^= result >> 16;
        result ^= result >> 8;
        result ^= result >> 4;
        result ^= result >> 2;
        result ^= result >> 1;
        result & 1
    }
}

impl Bitwise for u64 {
    type Output = u64;
    fn count(&self) -> u64 {
        let mut count = 0;
        let mut copy = *self;
        while copy != 0 {
            count += copy & 1;
            copy >>= 1;
        }
        count
    }

    fn parity(&self) -> u64 {
        let mut result = *self;
        result ^= result >> 32;
        result ^= result >> 16;
        result ^= result >> 8;
        result ^= result >> 4;
        result ^= result >> 2;
        result ^= result >> 1;
        result & 1
    }
}

impl Bitwise for u8 {
    type Output = u8;
    fn count(&self) -> u8 {
        let mut count = 0;
        let mut copy = *self;
        while copy != 0 {
            count += copy & 1;
            copy >>= 1;
        }
        count
    }

    fn parity(&self) -> u8 {
        let mut result = *self;
        result ^= result >> 4;
        result ^= result >> 2;
        result ^= result >> 1;
        result & 1
    }
}

impl<I> Bitwise for [I]
where
    I: Bitwise,
    <I as Bitwise>::Output: Into<usize>,
{
    type Output = usize;
    fn count(&self) -> usize {
        self.iter().fold(0, |val, el| {
            val + <<I as Bitwise>::Output as Into<usize>>::into(el.count())
        })
    }
    fn parity(&self) -> usize {
        self.iter().fold(0, |val, el| {
            val ^ <<I as Bitwise>::Output as Into<usize>>::into(el.parity())
        })
    }
}

#[cfg(feature = "dyn")]
impl<I> Bitwise for std::collections::VecDeque<I>
where
    I: Bitwise,
    <I as Bitwise>::Output: Into<usize>,
{
    type Output = usize;
    fn count(&self) -> usize {
        self.iter().fold(0, |val, el| {
            val + <<I as Bitwise>::Output as Into<usize>>::into(el.count())
        })
    }
    fn parity(&self) -> usize {
        self.iter().fold(0, |val, el| {
            val ^ <<I as Bitwise>::Output as Into<usize>>::into(el.parity())
        })
    }
}

#[test]
fn test_count() {
    assert_eq!(1u128.count(), 1);
    assert_eq!(2u128.count(), 1);
    assert_eq!(3u128.count(), 2);
    assert_eq!([2u8, 2, 5].count(), 4);
    assert_eq!([2u8, 2, 8].count(), 3);
}

#[test]
fn test_parity() {
    assert_eq!(1u128.parity(), 1);
    assert_eq!(2u128.parity(), 1);
    assert_eq!(3u128.parity(), 0);
    assert_eq!([2u8, 2, 5].parity(), 0);
    assert_eq!([2u8, 2, 8].parity(), 1);
}

#[cfg(feature = "nightly")]
#[bench]
fn parity_u64(b: &mut test::Bencher) {
    let mut guard = 1;
    let v = 0x1203_0245_2124_9151u64;
    b.iter(|| {
        for _ in 0..1_000_000usize {
            guard = v.parity()
        }
    });
}

#[cfg(feature = "nightly")]
#[bench]
fn parity_u8_8(b: &mut test::Bencher) {
    let mut guard = 1;
    let v = [0x12u8, 0x03, 0x02, 0x45, 0x21, 0x24, 0x91, 0x51];
    b.iter(|| {
        for _ in 0..1_000_000usize {
            guard = v.parity()
        }
    });
}

#[test]
fn test_count_parity() {
    for x in (0..100).map(|x| x * (core::u128::MAX / 100)) {
        assert_eq!(x.parity(), x.count() % 2);
    }
}