mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-27 21:02:35 +00:00
speed up rs implementation (still too slow)
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
use std::{fmt};
|
use std::fmt;
|
||||||
|
|
||||||
use crate::Exceptions;
|
use crate::Exceptions;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
@@ -64,9 +64,7 @@ pub fn get_predefined_genericgf(request: PredefinedGenericGF) -> GenericGFRef {
|
|||||||
match request {
|
match request {
|
||||||
PredefinedGenericGF::AztecData12 => &AZTEC_DATA_12, // x^12 + x^6 + x^5 + x^3 + 1,
|
PredefinedGenericGF::AztecData12 => &AZTEC_DATA_12, // x^12 + x^6 + x^5 + x^3 + 1,
|
||||||
PredefinedGenericGF::AztecData10 => &AZTEC_DATA_10, // x^10 + x^3 + 1
|
PredefinedGenericGF::AztecData10 => &AZTEC_DATA_10, // x^10 + x^3 + 1
|
||||||
PredefinedGenericGF::AztecData6 | PredefinedGenericGF::MaxicodeField64 => {
|
PredefinedGenericGF::AztecData6 | PredefinedGenericGF::MaxicodeField64 => &AZTEC_DATA_6, // x^6 + x + 1
|
||||||
&AZTEC_DATA_6
|
|
||||||
} // x^6 + x + 1
|
|
||||||
PredefinedGenericGF::AztecParam => &AZTEC_PARAM, // x^4 + x + 1
|
PredefinedGenericGF::AztecParam => &AZTEC_PARAM, // x^4 + x + 1
|
||||||
PredefinedGenericGF::QrCodeField256 => &QR_CODE_FIELD_256, // x^8 + x^4 + x^3 + x^2 + 1
|
PredefinedGenericGF::QrCodeField256 => &QR_CODE_FIELD_256, // x^8 + x^4 + x^3 + x^2 + 1
|
||||||
PredefinedGenericGF::DataMatrixField256 | PredefinedGenericGF::AztecData8 => {
|
PredefinedGenericGF::DataMatrixField256 | PredefinedGenericGF::AztecData8 => {
|
||||||
@@ -86,7 +84,7 @@ pub fn get_predefined_genericgf(request: PredefinedGenericGF) -> GenericGFRef {
|
|||||||
* @author Sean Owen
|
* @author Sean Owen
|
||||||
* @author David Olivier
|
* @author David Olivier
|
||||||
*/
|
*/
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct GenericGF {
|
pub struct GenericGF {
|
||||||
expTable: Vec<i32>,
|
expTable: Vec<i32>,
|
||||||
logTable: Vec<i32>,
|
logTable: Vec<i32>,
|
||||||
@@ -97,18 +95,6 @@ pub struct GenericGF {
|
|||||||
generatorBase: i32,
|
generatorBase: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hash for GenericGF {
|
|
||||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
||||||
self.to_string().hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl PartialEq for GenericGF {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.to_string() == other.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Eq for GenericGF {}
|
|
||||||
|
|
||||||
impl GenericGF {
|
impl GenericGF {
|
||||||
/**
|
/**
|
||||||
* Create a representation of GF(size) using the given primitive polynomial.
|
* Create a representation of GF(size) using the given primitive polynomial.
|
||||||
@@ -130,7 +116,7 @@ impl GenericGF {
|
|||||||
//expTable.push(x);
|
//expTable.push(x);
|
||||||
expTable[i] = x;
|
expTable[i] = x;
|
||||||
x *= 2; // we're assuming the generator alpha is 2
|
x *= 2; // we're assuming the generator alpha is 2
|
||||||
if x >= size.try_into().unwrap() {
|
if x >= size as i32 {
|
||||||
x ^= primitive;
|
x ^= primitive;
|
||||||
let sz_m_1: i32 = size as i32 - 1;
|
let sz_m_1: i32 = size as i32 - 1;
|
||||||
x &= sz_m_1;
|
x &= sz_m_1;
|
||||||
@@ -138,8 +124,8 @@ impl GenericGF {
|
|||||||
}
|
}
|
||||||
for i in 0..size - 1 {
|
for i in 0..size - 1 {
|
||||||
//for (int i = 0; i < size - 1; i++) {
|
//for (int i = 0; i < size - 1; i++) {
|
||||||
let loc: usize = expTable[i].try_into().unwrap();
|
let loc: usize = expTable[i] as usize;
|
||||||
logTable[loc] = i.try_into().unwrap();
|
logTable[loc] = i as i32;
|
||||||
}
|
}
|
||||||
logTable[0] = 0;
|
logTable[0] = 0;
|
||||||
|
|
||||||
@@ -157,8 +143,6 @@ impl GenericGF {
|
|||||||
// // for (i = 0; i < 255; i++)
|
// // for (i = 0; i < 255; i++)
|
||||||
// logTable[expTable[i].try_into().unwrap()] = i;
|
// logTable[expTable[i].try_into().unwrap()] = i;
|
||||||
// /*Note that we rely on the fact that _gf->log[0]=0 below.*/
|
// /*Note that we rely on the fact that _gf->log[0]=0 below.*/
|
||||||
logTable[0] = 0;
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
expTable,
|
expTable,
|
||||||
logTable,
|
logTable,
|
||||||
@@ -207,8 +191,8 @@ impl GenericGF {
|
|||||||
* @return 2 to the power of a in GF(size)
|
* @return 2 to the power of a in GF(size)
|
||||||
*/
|
*/
|
||||||
pub fn exp(&self, a: i32) -> i32 {
|
pub fn exp(&self, a: i32) -> i32 {
|
||||||
let pos: usize = a.try_into().unwrap();
|
// let pos: usize = a.try_into().unwrap();
|
||||||
return self.expTable[pos];
|
return self.expTable[a as usize];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -218,8 +202,8 @@ impl GenericGF {
|
|||||||
if a == 0 {
|
if a == 0 {
|
||||||
return Err(Exceptions::IllegalArgumentException("".to_owned()));
|
return Err(Exceptions::IllegalArgumentException("".to_owned()));
|
||||||
}
|
}
|
||||||
let pos: usize = a.try_into().unwrap();
|
// let pos: usize = a.try_into().unwrap();
|
||||||
return Ok(self.logTable[pos]);
|
return Ok(self.logTable[a as usize]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -229,10 +213,8 @@ impl GenericGF {
|
|||||||
if a == 0 {
|
if a == 0 {
|
||||||
return Err(Exceptions::ArithmeticException("".to_owned()));
|
return Err(Exceptions::ArithmeticException("".to_owned()));
|
||||||
}
|
}
|
||||||
let log_t_loc: usize = a.try_into().unwrap();
|
let log_t_loc: usize = a as usize;
|
||||||
let loc: usize = ((self.size as i32) - self.logTable[log_t_loc] - 1)
|
let loc: usize = ((self.size as i32) - self.logTable[log_t_loc] - 1) as usize;
|
||||||
.try_into()
|
|
||||||
.unwrap();
|
|
||||||
return Ok(self.expTable[loc]);
|
return Ok(self.expTable[loc]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,11 +225,9 @@ impl GenericGF {
|
|||||||
if a == 0 || b == 0 {
|
if a == 0 || b == 0 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
let a_loc: usize = a.try_into().unwrap();
|
let a_loc: usize = a as usize; //.try_into().unwrap();
|
||||||
let b_loc: usize = b.try_into().unwrap();
|
let b_loc: usize = b as usize; //.try_into().unwrap();
|
||||||
let comb_loc: usize = (self.logTable[a_loc] + self.logTable[b_loc])
|
let comb_loc: usize = (self.logTable[a_loc] + self.logTable[b_loc]) as usize;
|
||||||
.try_into()
|
|
||||||
.unwrap();
|
|
||||||
return self.expTable[comb_loc % (self.size - 1)];
|
return self.expTable[comb_loc % (self.size - 1)];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,19 +273,12 @@ impl fmt::Display for GenericGF {
|
|||||||
*
|
*
|
||||||
* @author Sean Owen
|
* @author Sean Owen
|
||||||
*/
|
*/
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct GenericGFPoly {
|
pub struct GenericGFPoly {
|
||||||
field: GenericGFRef,
|
field: GenericGFRef,
|
||||||
coefficients: Vec<i32>,
|
coefficients: Vec<i32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for GenericGFPoly {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
self.to_string() == other.to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Eq for GenericGFPoly {}
|
|
||||||
|
|
||||||
impl GenericGFPoly {
|
impl GenericGFPoly {
|
||||||
/**
|
/**
|
||||||
* @param field the {@link GenericGF} instance representing the field to use
|
* @param field the {@link GenericGF} instance representing the field to use
|
||||||
@@ -329,7 +302,8 @@ impl GenericGFPoly {
|
|||||||
if coefficients_length > 1 && coefficients[0] == 0 {
|
if coefficients_length > 1 && coefficients[0] == 0 {
|
||||||
// Leading term must be non-zero for anything except the constant polynomial "0"
|
// Leading term must be non-zero for anything except the constant polynomial "0"
|
||||||
let mut first_non_zero = 1;
|
let mut first_non_zero = 1;
|
||||||
while first_non_zero < coefficients_length && coefficients[first_non_zero] == 0 {
|
while first_non_zero < coefficients_length && coefficients[first_non_zero] == 0
|
||||||
|
{
|
||||||
first_non_zero += 1;
|
first_non_zero += 1;
|
||||||
}
|
}
|
||||||
if first_non_zero == coefficients_length {
|
if first_non_zero == coefficients_length {
|
||||||
@@ -399,10 +373,7 @@ impl GenericGFPoly {
|
|||||||
for i in 1..size {
|
for i in 1..size {
|
||||||
//for (int i = 1; i < size; i++) {
|
//for (int i = 1; i < size; i++) {
|
||||||
result = GenericGF::addOrSubtract(
|
result = GenericGF::addOrSubtract(
|
||||||
self.field
|
self.field.multiply(a as i32, result as i32),
|
||||||
.multiply(a.try_into().unwrap(), result.try_into().unwrap())
|
|
||||||
.try_into()
|
|
||||||
.unwrap(),
|
|
||||||
self.coefficients[i],
|
self.coefficients[i],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -469,13 +440,7 @@ impl GenericGFPoly {
|
|||||||
//for (int j = 0; j < bLength; j++) {
|
//for (int j = 0; j < bLength; j++) {
|
||||||
product[i + j] = GenericGF::addOrSubtract(
|
product[i + j] = GenericGF::addOrSubtract(
|
||||||
product[i + j],
|
product[i + j],
|
||||||
self.field
|
self.field.multiply(aCoeff, bCoefficients[j]),
|
||||||
.multiply(
|
|
||||||
aCoeff.try_into().unwrap(),
|
|
||||||
bCoefficients[j].try_into().unwrap(),
|
|
||||||
)
|
|
||||||
.try_into()
|
|
||||||
.unwrap(),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -494,9 +459,7 @@ impl GenericGFPoly {
|
|||||||
let mut product = vec![0; size];
|
let mut product = vec![0; size];
|
||||||
for i in 0..size {
|
for i in 0..size {
|
||||||
//for (int i = 0; i < size; i++) {
|
//for (int i = 0; i < size; i++) {
|
||||||
product[i] = self
|
product[i] = self.field.multiply(self.coefficients[i], scalar);
|
||||||
.field
|
|
||||||
.multiply(self.coefficients[i], scalar.try_into().unwrap());
|
|
||||||
}
|
}
|
||||||
return GenericGFPoly::new(self.field, &product).unwrap();
|
return GenericGFPoly::new(self.field, &product).unwrap();
|
||||||
}
|
}
|
||||||
@@ -514,9 +477,6 @@ impl GenericGFPoly {
|
|||||||
degree: usize,
|
degree: usize,
|
||||||
coefficient: i32,
|
coefficient: i32,
|
||||||
) -> Result<GenericGFPoly, Exceptions> {
|
) -> Result<GenericGFPoly, Exceptions> {
|
||||||
if degree < 0 {
|
|
||||||
return Err(Exceptions::IllegalArgumentException("".to_owned()));
|
|
||||||
}
|
|
||||||
if coefficient == 0 {
|
if coefficient == 0 {
|
||||||
return Ok(self.getZero());
|
return Ok(self.getZero());
|
||||||
}
|
}
|
||||||
@@ -680,16 +640,11 @@ impl ReedSolomonDecoder {
|
|||||||
*/
|
*/
|
||||||
pub fn decode(&self, received: &mut Vec<i32>, twoS: i32) -> Result<(), Exceptions> {
|
pub fn decode(&self, received: &mut Vec<i32>, twoS: i32) -> Result<(), Exceptions> {
|
||||||
let poly = GenericGFPoly::new(self.field, received).unwrap();
|
let poly = GenericGFPoly::new(self.field, received).unwrap();
|
||||||
let mut syndromeCoefficients = vec![0; twoS.try_into().unwrap()];
|
let mut syndromeCoefficients = vec![0; twoS as usize];
|
||||||
let mut noError = true;
|
let mut noError = true;
|
||||||
for i in 0..twoS {
|
for i in 0..twoS {
|
||||||
//for (int i = 0; i < twoS; i++) {
|
//for (int i = 0; i < twoS; i++) {
|
||||||
let eval = poly.evaluateAt(
|
let eval = poly.evaluateAt(self.field.exp(i + self.field.getGeneratorBase()) as usize);
|
||||||
self.field
|
|
||||||
.exp(i + self.field.getGeneratorBase())
|
|
||||||
.try_into()
|
|
||||||
.unwrap(),
|
|
||||||
);
|
|
||||||
let len = syndromeCoefficients.len();
|
let len = syndromeCoefficients.len();
|
||||||
syndromeCoefficients[len - 1 - i as usize] = eval;
|
syndromeCoefficients[len - 1 - i as usize] = eval;
|
||||||
if eval != 0 {
|
if eval != 0 {
|
||||||
@@ -708,9 +663,9 @@ impl ReedSolomonDecoder {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let sigmaOmega = self.runEuclideanAlgorithm(
|
let sigmaOmega = self.runEuclideanAlgorithm(
|
||||||
&GenericGF::buildMonomial(self.field, twoS.try_into().unwrap(), 1),
|
&GenericGF::buildMonomial(self.field, twoS as usize, 1),
|
||||||
&syndrome,
|
&syndrome,
|
||||||
twoS.try_into().unwrap(),
|
twoS as usize,
|
||||||
)?;
|
)?;
|
||||||
let sigma = &sigmaOmega[0];
|
let sigma = &sigmaOmega[0];
|
||||||
let omega = &sigmaOmega[1];
|
let omega = &sigmaOmega[1];
|
||||||
@@ -718,7 +673,7 @@ impl ReedSolomonDecoder {
|
|||||||
let errorMagnitudes = self.findErrorMagnitudes(&omega, &errorLocations);
|
let errorMagnitudes = self.findErrorMagnitudes(&omega, &errorLocations);
|
||||||
for i in 0..errorLocations.len() {
|
for i in 0..errorLocations.len() {
|
||||||
//for (int i = 0; i < errorLocations.length; i++) {
|
//for (int i = 0; i < errorLocations.length; i++) {
|
||||||
let log_value = self.field.log(errorLocations[i].try_into().unwrap())?;
|
let log_value = self.field.log(errorLocations[i] as i32)?;
|
||||||
if log_value > received.len() as i32 - 1 {
|
if log_value > received.len() as i32 - 1 {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -728,7 +683,8 @@ impl ReedSolomonDecoder {
|
|||||||
"Bad error location".to_owned(),
|
"Bad error location".to_owned(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
received[position as usize] = GenericGF::addOrSubtract(received[position as usize], errorMagnitudes[i]);
|
received[position as usize] =
|
||||||
|
GenericGF::addOrSubtract(received[position as usize], errorMagnitudes[i]);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -785,7 +741,8 @@ impl ReedSolomonDecoder {
|
|||||||
let scale = self
|
let scale = self
|
||||||
.field
|
.field
|
||||||
.multiply(r.getCoefficient(r.getDegree()), dltInverse);
|
.multiply(r.getCoefficient(r.getDegree()), dltInverse);
|
||||||
q = match q.addOrSubtract(&GenericGF::buildMonomial(self.field, degreeDiff, scale)) {
|
q = match q.addOrSubtract(&GenericGF::buildMonomial(self.field, degreeDiff, scale))
|
||||||
|
{
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(_err) => {
|
Err(_err) => {
|
||||||
return Err(Exceptions::ReedSolomonException(
|
return Err(Exceptions::ReedSolomonException(
|
||||||
@@ -861,7 +818,7 @@ impl ReedSolomonDecoder {
|
|||||||
let numErrors = errorLocator.getDegree();
|
let numErrors = errorLocator.getDegree();
|
||||||
if numErrors == 1 {
|
if numErrors == 1 {
|
||||||
// shortcut
|
// shortcut
|
||||||
return Ok(vec![errorLocator.getCoefficient(1).try_into().unwrap()]);
|
return Ok(vec![errorLocator.getCoefficient(1) as usize]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result: Vec<usize> = vec![0; numErrors];
|
let mut result: Vec<usize> = vec![0; numErrors];
|
||||||
@@ -872,8 +829,8 @@ impl ReedSolomonDecoder {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if errorLocator.evaluateAt(i) == 0 {
|
if errorLocator.evaluateAt(i) == 0 {
|
||||||
result[e] = match self.field.inverse(i.try_into().unwrap()) {
|
result[e] = match self.field.inverse(i as i32) {
|
||||||
Ok(res) => res.try_into().unwrap(),
|
Ok(res) => res as usize,
|
||||||
Err(_err) => {
|
Err(_err) => {
|
||||||
return Err(Exceptions::ReedSolomonException(
|
return Err(Exceptions::ReedSolomonException(
|
||||||
"ArithmetricException".to_owned(),
|
"ArithmetricException".to_owned(),
|
||||||
@@ -901,10 +858,7 @@ impl ReedSolomonDecoder {
|
|||||||
let mut result = vec![0; s];
|
let mut result = vec![0; s];
|
||||||
for i in 0..s {
|
for i in 0..s {
|
||||||
//for (int i = 0; i < s; i++) {
|
//for (int i = 0; i < s; i++) {
|
||||||
let xiInverse = self
|
let xiInverse = self.field.inverse(errorLocations[i] as i32).unwrap();
|
||||||
.field
|
|
||||||
.inverse(errorLocations[i].try_into().unwrap())
|
|
||||||
.unwrap();
|
|
||||||
let mut denominator = 1;
|
let mut denominator = 1;
|
||||||
for j in 0..s {
|
for j in 0..s {
|
||||||
//for (int j = 0; j < s; j++) {
|
//for (int j = 0; j < s; j++) {
|
||||||
@@ -913,9 +867,7 @@ impl ReedSolomonDecoder {
|
|||||||
// GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)));
|
// GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)));
|
||||||
// Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug.
|
// Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug.
|
||||||
// Below is a funny-looking workaround from Steven Parkes
|
// Below is a funny-looking workaround from Steven Parkes
|
||||||
let term = self
|
let term = self.field.multiply(errorLocations[j] as i32, xiInverse);
|
||||||
.field
|
|
||||||
.multiply(errorLocations[j].try_into().unwrap(), xiInverse);
|
|
||||||
let termPlus1 = if (term & 0x1) == 0 {
|
let termPlus1 = if (term & 0x1) == 0 {
|
||||||
term | 1
|
term | 1
|
||||||
} else {
|
} else {
|
||||||
@@ -925,7 +877,7 @@ impl ReedSolomonDecoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
result[i] = self.field.multiply(
|
result[i] = self.field.multiply(
|
||||||
errorEvaluator.evaluateAt(xiInverse.try_into().unwrap()),
|
errorEvaluator.evaluateAt(xiInverse as usize),
|
||||||
self.field.inverse(denominator).unwrap(),
|
self.field.inverse(denominator).unwrap(),
|
||||||
);
|
);
|
||||||
if self.field.getGeneratorBase() != 0 {
|
if self.field.getGeneratorBase() != 0 {
|
||||||
@@ -1026,7 +978,7 @@ impl ReedSolomonEncoder {
|
|||||||
info_coefficients[0..data_bytes].clone_from_slice(&to_encode[0..data_bytes]);
|
info_coefficients[0..data_bytes].clone_from_slice(&to_encode[0..data_bytes]);
|
||||||
//System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes);
|
//System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes);
|
||||||
let mut info = GenericGFPoly::new(fld, &info_coefficients)?;
|
let mut info = GenericGFPoly::new(fld, &info_coefficients)?;
|
||||||
info = info.multiply_by_monomial(ec_bytes.try_into().unwrap(), 1)?;
|
info = info.multiply_by_monomial(ec_bytes, 1)?;
|
||||||
let remainder = &info.divide(&generator)?.1;
|
let remainder = &info.divide(&generator)?.1;
|
||||||
let coefficients = remainder.getCoefficients();
|
let coefficients = remainder.getCoefficients();
|
||||||
let num_zero_coefficients = ec_bytes - coefficients.len();
|
let num_zero_coefficients = ec_bytes - coefficients.len();
|
||||||
|
|||||||
Reference in New Issue
Block a user