rxing/pdf417/decoder/ec/
modulus_poly.rs1use crate::common::Result;
18use crate::Exceptions;
19
20use super::ModulusGF;
21
22#[derive(Clone, Debug)]
26pub struct ModulusPoly {
27 field: &'static ModulusGF,
28 coefficients: Vec<u32>,
29}
30impl ModulusPoly {
31 pub fn new(field: &'static ModulusGF, coefficients: Vec<u32>) -> Result<ModulusPoly> {
32 if coefficients.is_empty() {
33 return Err(Exceptions::ILLEGAL_ARGUMENT);
34 }
35 let orig_coefs = coefficients.clone();
36 let mut coefficients = coefficients;
37 let coefficientsLength = coefficients.len();
38 if coefficientsLength > 1 && coefficients[0] == 0 {
39 let mut firstNonZero = 1;
41 while firstNonZero < coefficientsLength && coefficients[firstNonZero] == 0 {
42 firstNonZero += 1;
43 }
44 if firstNonZero == coefficientsLength {
45 coefficients = vec![0];
46 } else {
47 coefficients = vec![0u32; coefficientsLength - firstNonZero];
48 coefficients[..].copy_from_slice(&orig_coefs[firstNonZero..]);
49 }
55 }
56 Ok(ModulusPoly {
61 field,
62 coefficients,
63 })
66 }
67
68 pub fn getCoefficients(&self) -> &[u32] {
69 &self.coefficients
70 }
71
72 pub fn getDegree(&self) -> u32 {
76 self.coefficients.len() as u32 - 1
77 }
78
79 pub fn isZero(&self) -> bool {
83 self.coefficients[0] == 0
84 }
85
86 pub fn getCoefficient(&self, degree: usize) -> u32 {
90 self.coefficients[self.coefficients.len() - 1 - degree]
91 }
92
93 pub fn evaluateAt(&self, a: u32) -> u32 {
97 if a == 0 {
98 return self.getCoefficient(0);
100 }
101 if a == 1 {
102 let mut result = 0;
104 for coefficient in self.coefficients.iter() {
105 result = self.field.add(result, *coefficient);
107 }
108 return result;
109 }
110 let mut result = self.coefficients[0];
111 let size = self.coefficients.len();
112 for i in 1..size {
113 result = self
115 .field
116 .add(self.field.multiply(a, result), self.coefficients[i]);
117 }
118 result
119 }
120
121 pub fn add(&self, other: ModulusPoly) -> Result<ModulusPoly> {
122 if self.field != other.field {
123 return Err(Exceptions::illegal_argument_with(
124 "ModulusPolys do not have same ModulusGF field",
125 ));
126 }
127 if self.isZero() {
128 return Ok(other);
129 }
130 if other.isZero() {
131 return Ok(self.clone());
132 }
133
134 let mut smallerCoefficients = &self.coefficients;
135 let mut largerCoefficients = &other.coefficients;
136 if smallerCoefficients.len() > largerCoefficients.len() {
137 std::mem::swap(&mut smallerCoefficients, &mut largerCoefficients);
138 }
139 let mut sumDiff = vec![0_u32; largerCoefficients.len()];
140 let lengthDiff = largerCoefficients.len() - smallerCoefficients.len();
141 sumDiff[..lengthDiff].copy_from_slice(&largerCoefficients[..lengthDiff]);
143 for i in lengthDiff..largerCoefficients.len() {
146 sumDiff[i] = self
148 .field
149 .add(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);
150 }
151
152 ModulusPoly::new(self.field, sumDiff)
153 }
154
155 pub fn subtract(&self, other: ModulusPoly) -> Result<ModulusPoly> {
156 if self.field != other.field {
157 return Err(Exceptions::illegal_argument_with(
158 "ModulusPolys do not have same ModulusGF field",
159 ));
160 }
161 if other.isZero() {
162 return Ok(self.clone());
163 };
164 self.add(other.negative())
165 }
166
167 pub fn multiply(&self, other: ModulusPoly) -> Result<ModulusPoly> {
168 if !(self.field == other.field) {
169 return Err(Exceptions::illegal_argument_with(
170 "ModulusPolys do not have same ModulusGF field",
171 ));
172 }
173 if self.isZero() || other.isZero() {
174 return Ok(Self::getZero(self.field));
175 }
176 let aCoefficients = &self.coefficients;
177 let aLength = aCoefficients.len();
178 let bCoefficients = &other.coefficients;
179 let bLength = bCoefficients.len();
180 let mut product = vec![0u32; aLength + bLength - 1];
181 for i in 0..aLength {
182 let aCoeff = aCoefficients[i];
184 for j in 0..bLength {
185 product[i + j] = self.field.add(
187 product[i + j],
188 self.field.multiply(aCoeff, bCoefficients[j]),
189 );
190 }
191 }
192
193 ModulusPoly::new(self.field, product)
194 }
195
196 pub fn negative(&self) -> ModulusPoly {
197 let size = self.coefficients.len();
198 let mut negativeCoefficients = vec![0u32; size];
199 for (i, neg_coef) in negativeCoefficients.iter_mut().enumerate().take(size) {
200 *neg_coef = self.field.subtract(0, self.coefficients[i]);
202 }
203
204 ModulusPoly::new(self.field, negativeCoefficients)
205 .expect("should always generate with known goods")
206 }
207
208 pub fn multiplyByScaler(&self, scalar: u32) -> ModulusPoly {
209 if scalar == 0 {
210 return Self::getZero(self.field);
211 }
212 if scalar == 1 {
213 return self.clone();
214 }
215 let size = self.coefficients.len();
216 let mut product = vec![0u32; size];
217 for (i, prod) in product.iter_mut().enumerate().take(size) {
218 *prod = self.field.multiply(self.coefficients[i], scalar);
220 }
221
222 ModulusPoly::new(self.field, product).expect("should always generate with known goods")
223 }
224
225 pub fn multiplyByMonomial(&self, degree: usize, coefficient: u32) -> ModulusPoly {
226 if coefficient == 0 {
227 return Self::getZero(self.field);
228 }
229 let size = self.coefficients.len();
230 let mut product = vec![0u32; size + degree];
231 for (i, prod) in product.iter_mut().enumerate().take(size) {
232 *prod = self.field.multiply(self.coefficients[i], coefficient);
234 }
235
236 ModulusPoly::new(self.field, product).expect("should always generate with known goods")
237 }
238
239 pub fn getZero(field: &'static ModulusGF) -> ModulusPoly {
240 ModulusPoly::new(field, vec![0]).expect("should always generate with known goods")
241 }
242
243 pub fn getOne(field: &'static ModulusGF) -> ModulusPoly {
244 ModulusPoly::new(field, vec![1]).expect("should always generate with known goods")
245 }
246
247 pub fn buildMonomial(
248 field: &'static ModulusGF,
249 degree: usize,
250 coefficient: u32,
251 ) -> ModulusPoly {
252 if coefficient == 0 {
256 return Self::getZero(field);
257 }
258 let mut coefficients = vec![0_u32; degree + 1];
259 coefficients[0] = coefficient;
260
261 ModulusPoly::new(field, coefficients).expect("should always generate with known goods")
262 }
263}