rxing/pdf417/decoder/ec/
modulus_poly.rs

1/*
2 * Copyright 2012 ZXing authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use crate::common::Result;
18use crate::Exceptions;
19
20use super::ModulusGF;
21
22/**
23 * @author Sean Owen
24 */
25#[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            // Leading term must be non-zero for anything except the constant polynomial "0"
40            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                // System.arraycopy(coefficients,
50                //     firstNonZero,
51                //     this.coefficients,
52                //     0,
53                //     this.coefficients.length);
54            }
55        }
56        // } else {
57        //     coefficients = coefficients;
58        // }
59
60        Ok(ModulusPoly {
61            field,
62            coefficients,
63            // zero: Some(Self::getZero(field.clone())),
64            // one: Some(Self::getOne(field.clone())),
65        })
66    }
67
68    pub fn getCoefficients(&self) -> &[u32] {
69        &self.coefficients
70    }
71
72    /**
73     * @return degree of this polynomial
74     */
75    pub fn getDegree(&self) -> u32 {
76        self.coefficients.len() as u32 - 1
77    }
78
79    /**
80     * @return true iff this polynomial is the monomial "0"
81     */
82    pub fn isZero(&self) -> bool {
83        self.coefficients[0] == 0
84    }
85
86    /**
87     * @return coefficient of x^degree term in this polynomial
88     */
89    pub fn getCoefficient(&self, degree: usize) -> u32 {
90        self.coefficients[self.coefficients.len() - 1 - degree]
91    }
92
93    /**
94     * @return evaluation of this polynomial at a given point
95     */
96    pub fn evaluateAt(&self, a: u32) -> u32 {
97        if a == 0 {
98            // Just return the x^0 coefficient
99            return self.getCoefficient(0);
100        }
101        if a == 1 {
102            // Just the sum of the coefficients
103            let mut result = 0;
104            for coefficient in self.coefficients.iter() {
105                // for (int coefficient : coefficients) {
106                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            // for (int i = 1; i < size; i++) {
114            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        // Copy high-order terms only found in higher-degree polynomial's coefficients
142        sumDiff[..lengthDiff].copy_from_slice(&largerCoefficients[..lengthDiff]);
143        // System.arraycopy(largerCoefficients, 0, sumDiff, 0, lengthDiff);
144
145        for i in lengthDiff..largerCoefficients.len() {
146            // for (int i = lengthDiff; i < largerCoefficients.length; i++) {
147            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            // for (int i = 0; i < aLength; i++) {
183            let aCoeff = aCoefficients[i];
184            for j in 0..bLength {
185                // for (int j = 0; j < bLength; j++) {
186                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            // for (int i = 0; i < size; i++) {
201            *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            // for (int i = 0; i < size; i++) {
219            *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            // for (int i = 0; i < size; i++) {
233            *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 degree < 0 {
253        //   throw new IllegalArgumentException();
254        // }
255        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}