1const POLY: u8 = 0x1b;
17
18#[inline(always)]
20pub fn add(a: u8, b: u8) -> u8 {
21 a ^ b
22}
23
24#[inline]
27pub fn mul(mut a: u8, mut b: u8) -> u8 {
28 let mut result = 0u8;
29 for _ in 0..8 {
30 if b & 1 != 0 {
31 result ^= a;
32 }
33 let high = a & 0x80;
34 a <<= 1;
35 if high != 0 {
36 a ^= POLY;
37 }
38 b >>= 1;
39 }
40 result
41}
42
43#[inline]
48pub fn inv(a: u8) -> u8 {
49 assert!(a != 0, "gf256::inv: inverse of 0 is undefined");
50 let a2 = mul(a, a);
56 let a4 = mul(a2, a2);
57 let a8 = mul(a4, a4);
58 let a16 = mul(a8, a8);
59 let a32 = mul(a16, a16);
60 let a64 = mul(a32, a32);
61 let a128 = mul(a64, a64);
62 mul(mul(mul(mul(mul(mul(a2, a4), a8), a16), a32), a64), a128)
63}
64
65#[inline]
70pub fn div(a: u8, b: u8) -> u8 {
71 if a == 0 {
72 return 0;
73 }
74 mul(a, inv(b))
75}
76
77pub fn mul_acc(acc: &mut [u8], symbol: &[u8], coeff: u8) {
82 assert_eq!(acc.len(), symbol.len(), "gf256::mul_acc: length mismatch");
83 if coeff == 0 {
84 return;
85 }
86 if coeff == 1 {
87 for (a, &s) in acc.iter_mut().zip(symbol.iter()) {
88 *a ^= s;
89 }
90 return;
91 }
92 for (a, &s) in acc.iter_mut().zip(symbol.iter()) {
93 *a ^= mul(coeff, s);
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[test]
102 fn add_is_xor() {
103 assert_eq!(add(0x53, 0xca), 0x53 ^ 0xca);
104 }
105
106 #[test]
107 fn mul_known_value() {
108 assert_eq!(mul(0x53, 0xca), 0x01);
110 }
111
112 #[test]
113 fn mul_by_zero_and_one() {
114 assert_eq!(mul(0xff, 0x00), 0x00);
115 assert_eq!(mul(0x00, 0x53), 0x00);
116 assert_eq!(mul(0xab, 0x01), 0xab);
117 assert_eq!(mul(0x01, 0xcd), 0xcd);
118 }
119
120 #[test]
121 fn mul_commutative() {
122 for a in [0x00u8, 0x01, 0x53, 0xca, 0xff] {
123 for b in [0x00u8, 0x01, 0x53, 0xca, 0xff] {
124 assert_eq!(mul(a, b), mul(b, a));
125 }
126 }
127 }
128
129 #[test]
130 fn inv_times_self_is_one() {
131 for a in 1u8..=255 {
132 assert_eq!(mul(a, inv(a)), 1, "a*inv(a) != 1 for a={a:#x}");
133 }
134 }
135
136 #[test]
137 fn div_round_trip() {
138 assert_eq!(mul(div(0x53, 0x2b), 0x2b), 0x53);
139 }
140
141 #[test]
142 fn mul_acc_accumulates_correctly() {
143 let mut acc = vec![0u8; 3];
144 mul_acc(&mut acc, &[0x01, 0x02, 0x03], 0x02);
145 assert_eq!(acc[0], mul(0x02, 0x01));
146 assert_eq!(acc[1], mul(0x02, 0x02));
147 assert_eq!(acc[2], mul(0x02, 0x03));
148 }
149}