feat: GF(2^8) Galois 域运算 + 预计算 exp/log 表

This commit is contained in:
2026-06-16 23:31:26 +08:00
parent 8ff3086990
commit b292cec088
+166 -1
View File
@@ -1 +1,166 @@
// FIXME: GF(2⁸) Galois 域运算 — Task 2
/// GF(2⁸) Galois 域运算
/// 本原多项式: x⁸ + x⁴ + x³ + x² + 1 = 0x11D
/// 生成元 α = 0x02
use std::sync::OnceLock;
fn exp_table() -> &'static [u8; 512] {
static TABLE: OnceLock<[u8; 512]> = OnceLock::new();
TABLE.get_or_init(|| {
let mut table = [0u8; 512];
let mut x = 1u8;
for i in 0..255 {
table[i] = x;
table[i + 255] = x; // 双倍长度避免 % 255
let next = (x as u16) << 1;
x = if next >= 0x100 {
(next ^ 0x1D) as u8
} else {
next as u8
};
}
table[510] = table[255];
table[511] = table[256];
table
})
}
fn log_table() -> &'static [u8; 256] {
static TABLE: OnceLock<[u8; 256]> = OnceLock::new();
TABLE.get_or_init(|| {
let mut table = [0u8; 256];
let mut x = 1u8;
for i in 0..255 {
table[x as usize] = i;
let next = (x as u16) << 1;
x = if next >= 0x100 {
(next ^ 0x1D) as u8
} else {
next as u8
};
}
table
})
}
/// GF(2⁸) 加法 = 异或
#[inline]
pub fn add(a: u8, b: u8) -> u8 {
a ^ b
}
/// GF(2⁸) 减法 = 异或(同加法)
#[inline]
pub fn sub(a: u8, b: u8) -> u8 {
a ^ b
}
/// GF(2⁸) 乘法:a * b
pub fn mul(a: u8, b: u8) -> u8 {
if a == 0 || b == 0 {
return 0;
}
let log_a = log_table()[a as usize] as usize;
let log_b = log_table()[b as usize] as usize;
exp_table()[log_a + log_b]
}
/// GF(2⁸) 除法:a / b
pub fn div(a: u8, b: u8) -> u8 {
if a == 0 {
return 0;
}
if b == 0 {
panic!("GF(2⁸) 除以零");
}
let log_a = log_table()[a as usize] as usize;
let log_b = log_table()[b as usize] as usize;
let diff = (log_a + 255 - log_b) % 255;
exp_table()[diff]
}
/// GF(2⁸) 幂运算:base^exp
pub fn pow(base: u8, exp: usize) -> u8 {
if exp == 0 {
return 1;
}
if base == 0 {
return 0;
}
let log_b = log_table()[base as usize] as usize;
exp_table()[(log_b * exp) % 255]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mul_basic() {
// 2 * 3 = 6 in GF(2^8)
assert_eq!(mul(2, 3), 6);
// 0xFF * 0x01 = 0xFF
assert_eq!(mul(0xFF, 1), 0xFF);
// 任何数乘 0 = 0
assert_eq!(mul(0xA5, 0), 0);
}
#[test]
fn test_mul_commutative() {
for a in 0..=255u8 {
for b in (a..=255u8).step_by(17) {
assert_eq!(mul(a, b), mul(b, a),
"交换律失败: {:02X} * {:02X}", a, b);
}
}
}
#[test]
fn test_mul_associative() {
let cases = [(3, 5, 7), (0xFF, 2, 4), (1, 1, 1), (0x80, 0x40, 0x20)];
for (a, b, c) in cases {
assert_eq!(mul(mul(a, b), c), mul(a, mul(b, c)),
"结合律失败: {:02X} * {:02X} * {:02X}", a, b, c);
}
}
#[test]
fn test_div_inverse() {
for a in 1..=255u8 {
let inv = div(1, a);
assert_eq!(mul(a, inv), 1,
"逆元失败: {:02X} * {:02X} != 1", a, inv);
}
}
#[test]
fn test_div_mul_consistency() {
for a in 1..=255u8 {
for b in (1..=255u8).step_by(17) {
let q = div(a, b);
assert_eq!(mul(q, b), a,
"除乘一致性失败: {:02X} / {:02X} = {:02X}", a, q, b);
}
}
}
#[test]
fn test_add_sub() {
for a in 0..=255u8 {
for b in 0..=255u8 {
assert_eq!(add(a, b), sub(a, b));
assert_eq!(sub(add(a, b), b), a);
}
}
}
#[test]
fn test_pow() {
// α^0 = 1
assert_eq!(pow(2, 0), 1);
// α^1 = 2
assert_eq!(pow(2, 1), 2);
// α^7 * α^2 = α^9
assert_eq!(mul(pow(2, 7), pow(2, 2)), pow(2, 9));
}
}