qrcode_rust_shared/
qr_polynomial.rs1use crate::qr_math::QRMath;
4
5pub struct Polynomial {
8 pub num: Vec<i32>,
9}
10
11impl Polynomial {
12 pub fn new(num: Vec<i32>, _shift: i32) -> Self {
14 let mut start = 0;
16 let len = num.len();
17 while start < len - 1 && num[start] == 0 {
18 start += 1;
19 }
20
21 let num = if start > 0 {
22 num[start..].to_vec()
23 } else {
24 num
25 };
26
27 Polynomial { num }
28 }
29
30 pub fn get(&self, index: usize) -> i32 {
31 self.num.get(index).copied().unwrap_or(0)
32 }
33
34 pub fn len(&self) -> usize {
35 self.num.len()
36 }
37
38 pub fn is_empty(&self) -> bool {
39 self.num.is_empty()
40 }
41
42 pub fn multiply(&self, e: &Polynomial) -> Polynomial {
44 let mut num = vec![0; self.len() + e.len() - 1];
45
46 for i in 0..self.len() {
47 for j in 0..e.len() {
48 num[i + j] ^= QRMath::gexp(QRMath::glog(self.get(i)) + QRMath::glog(e.get(j)));
50 }
51 }
52
53 Polynomial::new(num, 0)
54 }
55
56 pub fn generate_rs_poly(ec_count: i32) -> Polynomial {
59 let mut result = Polynomial::new(vec![1], 0);
60
61 for i in 0..ec_count {
62 let factor = Polynomial::new(vec![1, QRMath::gexp(i)], 0);
63 result = result.multiply(&factor);
64 }
65
66 result
67 }
68
69 pub fn r#mod(&self, e: &Polynomial) -> Polynomial {
71 if (self.len() as i32 - e.len() as i32) < 0 {
72 return Polynomial::new(self.num.clone(), 0);
73 }
74
75 let ratio = QRMath::glog(self.get(0)) - QRMath::glog(e.get(0));
76
77 let mut num = self.num.clone();
78 for (i, item) in num.iter_mut().enumerate().take(e.len()) {
79 *item ^= QRMath::gexp(QRMath::glog(e.get(i)) + ratio);
80 }
81
82 Polynomial::new(num, 0).r#mod(e)
83 }
84
85 pub fn r#mod_with_shift(&self, e: &Polynomial, shift: i32) -> Polynomial {
87 let mut extended = self.num.clone();
88 extended.extend(std::iter::repeat_n(0, shift as usize));
89
90 let shifted_poly = Polynomial::new(extended, 0);
91 shifted_poly.r#mod(e)
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[test]
100 fn test_polynomial_new() {
101 let p = Polynomial::new(vec![1, 2, 3], 0);
102 assert_eq!(p.len(), 3);
103 assert_eq!(p.get(0), 1);
104 assert_eq!(p.get(1), 2);
105 assert_eq!(p.get(2), 3);
106 }
107
108 #[test]
109 fn test_polynomial_new_removes_leading_zeros() {
110 let p = Polynomial::new(vec![0, 0, 1, 2], 0);
111 assert_eq!(p.len(), 2);
112 assert_eq!(p.get(0), 1);
113 assert_eq!(p.get(1), 2);
114 }
115
116 #[test]
117 fn test_multiply_simple() {
118 let p1 = Polynomial::new(vec![1, 2], 0);
119 let p2 = Polynomial::new(vec![1, 3], 0);
120 let result = p1.multiply(&p2);
121
122 assert_eq!(result.get(0), 1);
123 assert_eq!(result.get(1), 1); assert_eq!(result.get(2), 6);
125 }
126
127 #[test]
128 fn test_generate_rs_poly() {
129 let poly = Polynomial::generate_rs_poly(2);
130 assert_eq!(poly.len(), 3);
131 assert_eq!(poly.get(0), 1);
132 }
133
134 #[test]
135 fn test_mod_result_degree() {
136 let divisor = Polynomial::generate_rs_poly(4);
137
138 for test_data in [
139 vec![1, 2, 3, 4, 5, 6, 7, 8],
140 vec![1, 0, 0, 0, 0, 0, 0, 0],
141 vec![255, 254, 253, 252],
142 ] {
143 let dividend = Polynomial::new(test_data, 0);
144 let remainder = dividend.r#mod(&divisor);
145 assert!(remainder.len() <= 4);
146 }
147 }
148
149 #[test]
150 fn test_mod_with_shift() {
151 let p = Polynomial::new(vec![1, 2, 3], 0);
152 let divisor = Polynomial::generate_rs_poly(4);
153 let result = p.r#mod_with_shift(&divisor, 4);
154 assert!(result.len() <= 4);
155 }
156}