qrcode_rust_shared/
qr_math.rs1pub struct QRMath;
5
6static mut EXP_TABLE: [i32; 256] = [0; 256];
7static mut LOG_TABLE: [i32; 256] = [0; 256];
8static INIT: std::sync::Once = std::sync::Once::new();
9
10fn init_tables() {
11 INIT.call_once(|| {
12 unsafe {
13 EXP_TABLE[0] = 1;
16 for i in 1..256 {
17 let mut v = EXP_TABLE[i - 1] << 1;
18 if v > 255 {
19 v ^= 0x11d; }
21 EXP_TABLE[i] = v;
22 }
23
24 for i in 0..255 {
26 LOG_TABLE[EXP_TABLE[i] as usize] = i as i32;
27 }
28 LOG_TABLE[0] = 0; }
30 });
31}
32
33impl QRMath {
34 pub fn glog(n: i32) -> i32 {
36 init_tables();
37 if n < 1 {
38 panic!("glog({})", n);
39 }
40 unsafe { LOG_TABLE[n as usize] }
41 }
42
43 pub fn gexp(n: i32) -> i32 {
45 init_tables();
46 let mut n = n;
47 while n < 0 {
48 n += 255;
49 }
50 while n >= 256 {
51 n -= 255;
52 }
53 unsafe { EXP_TABLE[n as usize] }
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn test_gexp_basic() {
63 assert_eq!(QRMath::gexp(0), 1);
64 assert_eq!(QRMath::gexp(1), 2);
65 assert_eq!(QRMath::gexp(2), 4);
66 }
67
68 #[test]
69 fn test_gexp_overflow() {
70 assert_eq!(QRMath::gexp(255), 1);
71 assert_eq!(QRMath::gexp(256), 2);
72 }
73
74 #[test]
75 fn test_gexp_negative() {
76 assert_eq!(QRMath::gexp(-1), QRMath::gexp(254));
77 }
78
79 #[test]
80 fn test_glog_basic() {
81 assert_eq!(QRMath::glog(1), 0);
82 assert_eq!(QRMath::glog(2), 1);
83 assert_eq!(QRMath::glog(4), 2);
84 }
85
86 #[test]
87 fn test_glog_gexp_inverse() {
88 for i in 0..255 {
89 let exp = QRMath::gexp(i);
90 let log = QRMath::glog(exp);
91 assert_eq!(log, i, "glog(gexp({})) failed", i);
92 }
93 }
94
95 #[test]
96 fn test_gexp_glog_inverse() {
97 for i in 1..256 {
98 let log = QRMath::glog(i);
99 let exp = QRMath::gexp(log);
100 assert_eq!(exp, i, "gexp(glog({})) failed", i);
101 }
102 }
103
104 #[test]
105 #[should_panic(expected = "glog(0)")]
106 fn test_glog_zero_panics() {
107 QRMath::glog(0);
108 }
109}