qred 0.1.2

A fast, light-footprint native QR code generator with custom color styling.
Documentation
pub struct GF28 {
    log: [u8; 256],
    exp: [u8; 256],
}

impl GF28 {
    pub fn new() -> Self {
        let mut log = [0u8; 256];
        let mut exp = [0u8; 256];

        // Generator element alpha = 2, irreducible polynomial 0x11D
        let mut x = 1u16;
        for i in 0..255 {
            exp[i] = x as u8;
            log[x as usize] = i as u8;

            x <<= 1;                // xtime shift
            if x & 0x100 != 0 {     // 0x100 = 0b100000000
                x ^= 0x11D;         // XOR reduction for polynomial beyond degree 7
            }
        }
        exp[255] = exp[0];

        Self { log, exp }
    }

    pub fn mul(&self, a: u8, b: u8) -> u8 {
        if a == 0 || b == 0 {
            return 0;
        }

        let log_a = self.log[a as usize] as usize;
        let log_b = self.log[b as usize] as usize;
        self.exp[(log_a + log_b) % 255]
    }

    pub fn exp(&self, power: usize) -> u8 {
        self.exp[power % 255]
    }

    #[inline]
    pub fn add(&self, a: u8, b: u8) -> u8 {
        a ^ b   // addition in GF(2^8) = XOR
    }
}


// TESTS

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

    #[test]
    fn test_gf_multiplication() {
        let gf = GF28::new();

        // 0 multiplied by anything is 0
        assert_eq!(gf.mul(0, 123), 0);
        assert_eq!(gf.mul(45, 0), 0);

        // Alpha power checks
        assert_eq!(gf.exp(0), 1);
        assert_eq!(gf.exp(1), 2);
        assert_eq!(gf.exp(8), 29); // 2^8 mod 0x11D = 285 ^ 256 = 29

        // Known GF(2^8) multiplication values
        assert_eq!(gf.mul(3, 7), 9);
        assert_eq!(gf.mul(32, 8), 29);
    }
}