crispii_bits 1.0.0

Bit related functionality intended for use with Crispii
Documentation
use crate::{
    enums::PosU64,
    traits::AddWithCarry,
};

impl AddWithCarry for u64 {
    type Pos = PosU64;

    fn add_with_carry(self, other: Self) -> (Self, Vec<PosU64>) {
        let mut result: u64 = 0;
        let mut carry_bit: u8 = 0;
        
        let mut carried_bits: Vec<PosU64> = Vec::new();

        for i in 0..64 {
            let self_bit = (self >> i) & 1;
            let other_bit = (other >> i) & 1;

            let sum = self_bit + other_bit + (carry_bit as u64);

            if sum > 1 {
                carried_bits.push(PosU64::try_from(i as u8).expect("i is guaranteed to be within the legal range of PosU64"));

                carry_bit = 1;
            } else {
                carry_bit = 0;
            }

            if sum % 2 == 1 {
                result |= 1 << i;
            }
        }

        (result, carried_bits)
    }
}

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

    #[test]
    fn min_add_max() {
        let (result, carried_bits) = 0.add_with_carry(u64::MAX);

        assert_eq!(result, u64::MAX);
        assert_eq!(carried_bits.len(), 0);
    }

    #[test]
    fn max_add_one() {
        let (result, carried_bits) = u64::MAX.add_with_carry(1);

        assert_eq!(result, 0);

        let expected_carried_bits = vec![
            PosU64::B0,
            PosU64::B1,
            PosU64::B2,
            PosU64::B3,
            PosU64::B4,
            PosU64::B5,
            PosU64::B6,
            PosU64::B7,
            PosU64::B8,
            PosU64::B9,
            PosU64::B10,
            PosU64::B11,
            PosU64::B12,
            PosU64::B13,
            PosU64::B14,
            PosU64::B15,
            PosU64::B16,
            PosU64::B17,
            PosU64::B18,
            PosU64::B19,
            PosU64::B20,
            PosU64::B21,
            PosU64::B22,
            PosU64::B23,
            PosU64::B24,
            PosU64::B25,
            PosU64::B26,
            PosU64::B27,
            PosU64::B28,
            PosU64::B29,
            PosU64::B30,
            PosU64::B31,
            PosU64::B32,
            PosU64::B33,
            PosU64::B34,
            PosU64::B35,
            PosU64::B36,
            PosU64::B37,
            PosU64::B38,
            PosU64::B39,
            PosU64::B40,
            PosU64::B41,
            PosU64::B42,
            PosU64::B43,
            PosU64::B44,
            PosU64::B45,
            PosU64::B46,
            PosU64::B47,
            PosU64::B48,
            PosU64::B49,
            PosU64::B50,
            PosU64::B51,
            PosU64::B52,
            PosU64::B53,
            PosU64::B54,
            PosU64::B55,
            PosU64::B56,
            PosU64::B57,
            PosU64::B58,
            PosU64::B59,
            PosU64::B60,
            PosU64::B61,
            PosU64::B62,
            PosU64::B63,
        ];

        for &expected_carried_bit in &expected_carried_bits {
            assert!(carried_bits.contains(&expected_carried_bit), "Expected carried bit '{expected_carried_bit}' not found");
        }
    }
}