working through errors to compile

This commit is contained in:
Henry Schimke
2022-08-26 17:21:46 -05:00
parent 3f1f6941bb
commit 106eed1721
5 changed files with 317 additions and 287 deletions

View File

@@ -38,18 +38,18 @@ const DECODER_TEST_ITERATIONS: i32 = 10;
fn testDataMatrix() {
// real life test cases
testEncodeDecode(
super::DATA_MATRIX_FIELD_256,
vec![142, 164, 186],
vec![114, 25, 5, 88, 102],
&super::DATA_MATRIX_FIELD_256,
&vec![142, 164, 186],
&vec![114, 25, 5, 88, 102],
);
testEncodeDecode(
super::DATA_MATRIX_FIELD_256,
vec![
&super::DATA_MATRIX_FIELD_256,
&vec![
0x69, 0x75, 0x75, 0x71, 0x3B, 0x30, 0x30, 0x64, 0x70, 0x65, 0x66, 0x2F, 0x68, 0x70,
0x70, 0x68, 0x6D, 0x66, 0x2F, 0x64, 0x70, 0x6E, 0x30, 0x71, 0x30, 0x7B, 0x79, 0x6A,
0x6F, 0x68, 0x30, 0x81, 0xF0, 0x88, 0x1F, 0xB5,
],
vec![
&vec![
0x1C, 0x64, 0xEE, 0xEB, 0xD0, 0x1D, 0x00, 0x03, 0xF0, 0x1C, 0xF1, 0xD0, 0x6D, 0x00,
0x98, 0xDA, 0x80, 0x88, 0xBE, 0xFF, 0xB7, 0xFA, 0xA9, 0x95,
],
@@ -64,21 +64,21 @@ fn testDataMatrix() {
fn testQRCode() {
// Test case from example given in ISO 18004, Annex I
testEncodeDecode(
super::QR_CODE_FIELD_256,
vec![
&super::QR_CODE_FIELD_256,
&vec![
0x10, 0x20, 0x0C, 0x56, 0x61, 0x80, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11,
0xEC, 0x11,
],
vec![0xA5, 0x24, 0xD4, 0xC1, 0xED, 0x36, 0xC7, 0x87, 0x2C, 0x55],
&vec![0xA5, 0x24, 0xD4, 0xC1, 0xED, 0x36, 0xC7, 0x87, 0x2C, 0x55],
);
testEncodeDecode(
super::QR_CODE_FIELD_256,
vec![
&super::QR_CODE_FIELD_256,
&vec![
0x72, 0x67, 0x2F, 0x77, 0x69, 0x6B, 0x69, 0x2F, 0x4D, 0x61, 0x69, 0x6E, 0x5F, 0x50,
0x61, 0x67, 0x65, 0x3B, 0x3B, 0x00, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11,
0xEC, 0x11, 0xEC, 0x11,
],
vec![
&vec![
0xD8, 0xB8, 0xEF, 0x14, 0xEC, 0xD0, 0xCC, 0x85, 0x73, 0x40, 0x0B, 0xB5, 0x5A, 0xB8,
0x8B, 0x2E, 0x08, 0x62,
],
@@ -94,35 +94,35 @@ fn testQRCode() {
fn testAztec() {
// real life test cases
testEncodeDecode(
super::AZTEC_PARAM,
vec![0x5, 0x6],
vec![0x3, 0x2, 0xB, 0xB, 0x7],
&super::AZTEC_PARAM,
&vec![0x5, 0x6],
&vec![0x3, 0x2, 0xB, 0xB, 0x7],
);
testEncodeDecode(
super::AZTEC_PARAM,
vec![0x0, 0x0, 0x0, 0x9],
vec![0xA, 0xD, 0x8, 0x6, 0x5, 0x6],
&super::AZTEC_PARAM,
&vec![0x0, 0x0, 0x0, 0x9],
&vec![0xA, 0xD, 0x8, 0x6, 0x5, 0x6],
);
testEncodeDecode(
super::AZTEC_PARAM,
vec![0x2, 0x8, 0x8, 0x7],
vec![0xE, 0xC, 0xA, 0x9, 0x6, 0x8],
&super::AZTEC_PARAM,
&vec![0x2, 0x8, 0x8, 0x7],
&vec![0xE, 0xC, 0xA, 0x9, 0x6, 0x8],
);
testEncodeDecode(
super::AZTEC_DATA_6,
vec![0x9, 0x32, 0x1, 0x29, 0x2F, 0x2, 0x27, 0x25, 0x1, 0x1B],
vec![0x2C, 0x2, 0xD, 0xD, 0xA, 0x16, 0x28, 0x9, 0x22, 0xA, 0x14],
&super::AZTEC_DATA_6,
&vec![0x9, 0x32, 0x1, 0x29, 0x2F, 0x2, 0x27, 0x25, 0x1, 0x1B],
&vec![0x2C, 0x2, 0xD, 0xD, 0xA, 0x16, 0x28, 0x9, 0x22, 0xA, 0x14],
);
testEncodeDecode(
super::AZTEC_DATA_8,
vec![
&super::AZTEC_DATA_8,
&vec![
0xE0, 0x86, 0x42, 0x98, 0xE8, 0x4A, 0x96, 0xC6, 0xB9, 0xF0, 0x8C, 0xA7, 0x4A, 0xDA,
0xF8, 0xCE, 0xB7, 0xDE, 0x88, 0x64, 0x29, 0x8E, 0x84, 0xA9, 0x6C, 0x6B, 0x9F, 0x08,
0xCA, 0x74, 0xAD, 0xAF, 0x8C, 0xEB, 0x7C, 0x10, 0xC8, 0x53, 0x1D, 0x09, 0x52, 0xD8,
0xD7, 0x3E, 0x11, 0x94, 0xE9, 0x5B, 0x5F, 0x19, 0xD6, 0xFB, 0xD1, 0x0C, 0x85, 0x31,
0xD0, 0x95, 0x2D, 0x8D, 0x73, 0xE1, 0x19, 0x4E, 0x95, 0xB5, 0xF1, 0x9D, 0x6F,
],
vec![
&vec![
0x31, 0xD7, 0x04, 0x46, 0xB2, 0xC1, 0x06, 0x94, 0x17, 0xE5, 0x0C, 0x2B, 0xA3, 0x99,
0x15, 0x7F, 0x16, 0x3C, 0x66, 0xBA, 0x33, 0xD9, 0xE8, 0x87, 0x86, 0xBB, 0x4B, 0x15,
0x4E, 0x4A, 0xDE, 0xD4, 0xED, 0xA1, 0xF8, 0x47, 0x2A, 0x50, 0xA6, 0xBC, 0x53, 0x7D,
@@ -130,8 +130,8 @@ fn testAztec() {
],
);
testEncodeDecode(
super::AZTEC_DATA_10,
vec![
&super::AZTEC_DATA_10,
&vec![
0x15C, 0x1E1, 0x2D5, 0x02E, 0x048, 0x1E2, 0x037, 0x0CD, 0x02E, 0x056, 0x26A, 0x281,
0x1C2, 0x1A6, 0x296, 0x045, 0x041, 0x0AA, 0x095, 0x2CE, 0x003, 0x38F, 0x2CD, 0x1A2,
0x036, 0x1AD, 0x04E, 0x090, 0x271, 0x0D3, 0x02E, 0x0D5, 0x2D4, 0x032, 0x2CA, 0x281,
@@ -161,7 +161,7 @@ fn testAztec() {
0x201, 0x0AA, 0x04E, 0x004, 0x1B0, 0x070, 0x275, 0x154, 0x026, 0x2C1, 0x2B3, 0x154,
0x2AA, 0x256, 0x0C1, 0x044, 0x004, 0x23F,
],
vec![
&vec![
0x379, 0x099, 0x348, 0x010, 0x090, 0x196, 0x09C, 0x1FF, 0x1B0, 0x32D, 0x244, 0x0DE,
0x201, 0x386, 0x163, 0x11F, 0x39B, 0x344, 0x3FE, 0x02F, 0x188, 0x113, 0x3D9, 0x102,
0x04A, 0x2E1, 0x1D1, 0x18E, 0x077, 0x262, 0x241, 0x20D, 0x1B8, 0x11D, 0x0D0, 0x0A5,
@@ -177,8 +177,8 @@ fn testAztec() {
],
);
testEncodeDecode(
super::AZTEC_DATA_12,
vec![
&super::AZTEC_DATA_12,
&vec![
0x571, 0xE1B, 0x542, 0xE12, 0x1E2, 0x0DC, 0xCD0, 0xB85, 0x69A, 0xA81, 0x709, 0xA6A,
0x584, 0x510, 0x4AA, 0x256, 0xCE0, 0x0F8, 0xFB3, 0x5A2, 0x0D9, 0xAD1, 0x389, 0x09C,
0x4D3, 0x0B8, 0xD5B, 0x503, 0x2B2, 0xA81, 0x2A8, 0x4E0, 0x92D, 0x3A5, 0xA81, 0x388,
@@ -283,7 +283,7 @@ fn testAztec() {
0x10C, 0x835, 0x429, 0x33C, 0xB33, 0x4D5, 0x509, 0xCCD, 0x550, 0x35B, 0x4E2, 0xAA0,
0x5E6, 0x205, 0xB09, 0x99C, 0x09F,
],
vec![
&vec![
0xD54, 0x221, 0x154, 0x7CD, 0xBF3, 0x112, 0x89B, 0xC5E, 0x9CD, 0x07E, 0xFB6, 0x78F,
0x7FA, 0x16F, 0x377, 0x4B4, 0x62D, 0x475, 0xBC2, 0x861, 0xB72, 0x9D0, 0x76A, 0x5A1,
0x22A, 0xF74, 0xDBA, 0x8B1, 0x139, 0xDCD, 0x012, 0x293, 0x705, 0xA34, 0xDD5, 0x3D2,
@@ -335,11 +335,11 @@ fn testAztec() {
testEncodeDecodeRandom(super::AZTEC_DATA_12, 3072, 1023);
}
fn corrupt(received: &mut Vec<i32>, howMany: i32, random: &rand::rngs::ThreadRng, max: i32) {
let corrupted = vec![false; received.len()];
fn corrupt(received: &mut Vec<i32>, howMany: i32, random: &mut rand::rngs::ThreadRng, max: i32) {
let mut corrupted = vec![false; received.len()];
//BitSet corrupted = new BitSet(received.length);
let mut skip = false;
for j in 0..howMany {
for _j in 0..howMany {
//for (int j = 0; j < howMany; j++) {
if skip {
skip = false;
@@ -367,17 +367,17 @@ fn testEncodeDecodeRandom(field: GenericGF, dataSize: usize, ecSize: usize) {
"Invalid ECC size for {}",
field
);
let encoder = ReedSolomonEncoder::new(Box::new(field));
let message = Vec::with_capacity(dataSize + ecSize);
let dataWords: Vec<i32> = Vec::with_capacity(dataSize);
let ecWords = Vec::with_capacity(ecSize);
let random = getPseudoRandom();
let encoder = ReedSolomonEncoder::new(Box::new(field.clone()));
let mut message = Vec::with_capacity(dataSize + ecSize);
let mut dataWords: Vec<i32> = Vec::with_capacity(dataSize);
let mut ecWords = Vec::with_capacity(ecSize);
let mut random = getPseudoRandom();
let iterations = if field.getSize() > 256 {
1
} else {
DECODER_RANDOM_TEST_ITERATIONS
};
for i in 0..iterations {
for _i in 0..iterations {
//for (int i = 0; i < iterations; i++) {
// generate random data
for k in 0..dataSize {
@@ -391,19 +391,19 @@ fn testEncodeDecodeRandom(field: GenericGF, dataSize: usize, ecSize: usize) {
ecWords[0..ecSize].clone_from_slice(&message[dataSize..ecSize]);
//System.arraycopy(message, dataSize, ecWords, 0, ecSize);
// check to see if Decoder can fix up to ecWords/2 random errors
testDecoder(field, dataWords, ecWords);
testDecoder(&field, &dataWords, &ecWords);
}
}
fn testEncodeDecode(field: GenericGF, dataWords: Vec<i32>, ecWords: Vec<i32>) {
fn testEncodeDecode(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
testEncoder(field, dataWords, ecWords);
testDecoder(field, dataWords, ecWords);
}
fn testEncoder(field: GenericGF, dataWords: Vec<i32>, ecWords: Vec<i32>) {
let encoder = ReedSolomonEncoder::new(Box::new(field));
let messageExpected = Vec::with_capacity(dataWords.len() + ecWords.len());
let message = Vec::with_capacity(dataWords.len() + ecWords.len());
fn testEncoder(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
let encoder = ReedSolomonEncoder::new(Box::new(field.clone()));
let mut messageExpected = Vec::with_capacity(dataWords.len() + ecWords.len());
let mut message = Vec::with_capacity(dataWords.len() + ecWords.len());
messageExpected[0..dataWords.len()].clone_from_slice(&dataWords[0..dataWords.len()]);
//System.arraycopy(dataWords, 0, messageExpected, 0, dataWords.len());
messageExpected[dataWords.len()..ecWords.len()].clone_from_slice(&ecWords[..ecWords.len()]);
@@ -418,24 +418,24 @@ fn testEncoder(field: GenericGF, dataWords: Vec<i32>, ecWords: Vec<i32>) {
dataWords.len(),
ecWords.len()
),
messageExpected,
message,
&messageExpected,
&message,
);
}
fn testDecoder(field: GenericGF, dataWords: Vec<i32>, ecWords: Vec<i32>) {
let decoder = ReedSolomonDecoder::new(field);
let message = Vec::with_capacity(dataWords.len() + ecWords.len());
fn testDecoder(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
let decoder = ReedSolomonDecoder::new(field.clone());
let mut message = Vec::with_capacity(dataWords.len() + ecWords.len());
let maxErrors = ecWords.len() / 2;
let random = getPseudoRandom();
let mut random = getPseudoRandom();
let iterations = if field.getSize() > 256 {
1
} else {
DECODER_TEST_ITERATIONS
};
for j in 0..iterations {
for _j in 0..iterations {
//for (int j = 0; j < iterations; j++) {
for i in 0..ecWords.len() {
for mut i in 0..ecWords.len() {
//for (int i = 0; i < ecWords.length; i++) {
if i > 10 && i < ecWords.len() / 2 - 10 {
// performance improvement - skip intermediate cases in long-running tests
@@ -448,7 +448,7 @@ fn testDecoder(field: GenericGF, dataWords: Vec<i32>, ecWords: Vec<i32>) {
corrupt(
&mut message,
i.try_into().unwrap(),
&random,
&mut random,
field.getSize().try_into().unwrap(),
);
@@ -489,15 +489,15 @@ fn testDecoder(field: GenericGF, dataWords: Vec<i32>, ecWords: Vec<i32>) {
ecWords.len(),
i
),
dataWords,
message,
&dataWords,
&message,
);
}
}
}
}
fn assertDataEquals(message: String, expected: Vec<i32>, received: Vec<i32>) {
fn assertDataEquals(message: String, expected: &Vec<i32>, received: &Vec<i32>) {
for i in 0..expected.len() {
//for (int i = 0; i < expected.length; i++) {
if expected[i] != received[i] {
@@ -514,7 +514,7 @@ fn assertDataEquals(message: String, expected: Vec<i32>, received: Vec<i32>) {
}
fn arrayToString(data: &[i32]) -> String {
let sb = String::from("{");
let mut sb = String::from("{");
for i in 0..data.len() {
//for (int i = 0; i < data.length; i++) {
//sb.append(String.format(i > 0 ? ",%X" : "%X", data[i]));

View File

@@ -89,12 +89,12 @@ pub const MAXICODE_FIELD_64: GenericGF = AZTEC_DATA_6;
* @author Sean Owen
* @author David Olivier
*/
#[derive(Debug)]
#[derive(Debug,Clone)]
pub struct GenericGF {
expTable: Vec<i32>,
logTable: Vec<i32>,
zero: Box<GenericGFPoly>,
one: Box<GenericGFPoly>,
// zero: Box<GenericGFPoly>,
// one: Box<GenericGFPoly>,
size: usize,
primitive: i32,
generatorBase: i32,
@@ -125,18 +125,12 @@ impl GenericGF {
* In most cases it should be 1, but for QR code it is 0.
*/
pub fn new(primitive: i32, size: usize, b: i32) -> Self {
let mut new_ggf: Self;
new_ggf.primitive = primitive;
new_ggf.size = size;
new_ggf.generatorBase = b;
new_ggf.expTable = Vec::with_capacity(size);
new_ggf.logTable = Vec::with_capacity(size);
let mut expTable = Vec::with_capacity(size);
let mut logTable = Vec::with_capacity(size);
let mut x = 1;
for i in 0..size {
//for (int i = 0; i < size; i++) {
new_ggf.expTable[i] = x;
expTable[i] = x;
x *= 2; // we're assuming the generator alpha is 2
if x >= size.try_into().unwrap() {
x ^= primitive;
@@ -146,35 +140,43 @@ impl GenericGF {
}
for i in 0..size {
//for (int i = 0; i < size - 1; i++) {
let loc: usize = new_ggf.expTable[i].try_into().unwrap();
new_ggf.logTable[loc] = i.try_into().unwrap();
let loc: usize = expTable[i].try_into().unwrap();
logTable[loc] = i.try_into().unwrap();
}
Self {
expTable,
logTable,
size,
primitive,
generatorBase: b,
}
// logTable[0] == 0 but this should never be used
new_ggf.zero = Box::new(GenericGFPoly::new(Box::new(new_ggf), &vec![0]).unwrap());
new_ggf.one = Box::new(GenericGFPoly::new(Box::new(new_ggf), &vec![1]).unwrap());
// new_ggf.zero = Box::new(GenericGFPoly::new(Box::new(new_ggf), &vec![0]).unwrap());
// new_ggf.one = Box::new(GenericGFPoly::new(Box::new(new_ggf), &vec![1]).unwrap());
new_ggf
//new_ggf
}
pub fn getZero(&self) -> Box<GenericGFPoly> {
return self.zero;
}
// pub fn getZero(&self) -> Box<GenericGFPoly> {
// return self.zero;
// }
pub fn getOne(&self) -> Box<GenericGFPoly> {
return self.one;
}
// pub fn getOne(&self) -> Box<GenericGFPoly> {
// return self.one;
// }
/**
* @return the monomial representing coefficient * x^degree
*/
pub fn buildMonomial(&self, degree: usize, coefficient: i32) -> Box<GenericGFPoly> {
pub fn buildMonomial(&self, degree: usize, coefficient: i32) -> GenericGFPoly {
if coefficient == 0 {
return self.zero;
return GenericGFPoly::new(self.clone(), &vec![0]).unwrap();
}
let coefficients = Vec::with_capacity(degree + 1);
let mut coefficients = Vec::with_capacity(degree + 1);
coefficients[0] = coefficient;
return Box::new(GenericGFPoly::new(Box::new(*self), &coefficients).unwrap());
return GenericGFPoly::new(self.clone(), &coefficients).unwrap();
}
/**
@@ -276,9 +278,9 @@ impl fmt::Display for GenericGF {
*
* @author Sean Owen
*/
#[derive(Debug)]
#[derive(Debug,Clone)]
pub struct GenericGFPoly {
field: Box<GenericGF>,
field: GenericGF,
coefficients: Vec<i32>,
}
@@ -300,7 +302,7 @@ impl GenericGFPoly {
* constant polynomial (that is, it is not the monomial "0")
*/
pub fn new(
field: Box<GenericGF>,
field: GenericGF,
coefficients: &Vec<i32>,
) -> Result<Self, IllegalArgumentException> {
if coefficients.len() == 0 {
@@ -321,8 +323,9 @@ impl GenericGFPoly {
} else {
let mut new_coefficients =
Vec::with_capacity(coefficientsLength - firstNonZero);
new_coefficients[0..new_coefficients.len()]
.clone_from_slice(&coefficients[firstNonZero..new_coefficients.len()]);
let l = new_coefficients.len();
new_coefficients[0..l]
.clone_from_slice(&coefficients[firstNonZero..l]);
// System.arraycopy(coefficients,
// firstNonZero,
// this.coefficients,
@@ -337,8 +340,8 @@ impl GenericGFPoly {
})
}
pub fn getCoefficients(&self) -> Vec<i32> {
return self.coefficients;
pub fn getCoefficients(&self) -> &Vec<i32> {
return &self.coefficients;
}
/**
@@ -373,9 +376,9 @@ impl GenericGFPoly {
if a == 1 {
// Just the sum of the coefficients
let mut result = 0;
for coefficient in self.coefficients {
for coefficient in &self.coefficients {
//for (int coefficient : coefficients) {
result = GenericGF::addOrSubtract(result, coefficient);
result = GenericGF::addOrSubtract(result, *coefficient);
}
return result;
}
@@ -396,22 +399,22 @@ impl GenericGFPoly {
pub fn addOrSubtract(
&self,
other: Box<GenericGFPoly>,
) -> Result<Box<GenericGFPoly>, IllegalArgumentException> {
other: &GenericGFPoly,
) -> Result<GenericGFPoly, IllegalArgumentException> {
if self.field != other.field {
return Err(IllegalArgumentException::new(
"GenericGFPolys do not have same GenericGF field",
));
}
if self.isZero() {
return Ok(other);
return Ok(other.clone());
}
if other.isZero() {
return Ok(Box::new(*self));
return Ok(self.clone());
}
let mut smallerCoefficients = self.coefficients;
let mut largerCoefficients = other.coefficients;
let mut smallerCoefficients = self.coefficients.clone();
let mut largerCoefficients = other.coefficients.clone();
if smallerCoefficients.len() > largerCoefficients.len() {
let temp = smallerCoefficients;
smallerCoefficients = largerCoefficients;
@@ -432,13 +435,13 @@ impl GenericGFPoly {
);
}
return Ok(Box::new(GenericGFPoly::new(self.field, &sumDiff)?));
return Ok(GenericGFPoly::new(self.field.clone(), &sumDiff)?);
}
pub fn multiply(
&self,
other: &GenericGFPoly,
) -> Result<Box<GenericGFPoly>, IllegalArgumentException> {
) -> Result<GenericGFPoly, IllegalArgumentException> {
if self.field != other.field {
//if (!field.equals(other.field)) {
return Err(IllegalArgumentException::new(
@@ -446,13 +449,13 @@ impl GenericGFPoly {
));
}
if self.isZero() || other.isZero() {
return Ok(self.field.getZero());
return Ok(self.getZero());
}
let aCoefficients = self.coefficients;
let aCoefficients = self.coefficients.clone();
let aLength = aCoefficients.len();
let bCoefficients = other.coefficients;
let bCoefficients = other.coefficients.clone();
let bLength = bCoefficients.len();
let product = Vec::with_capacity(aLength + bLength - 1);
let mut product = Vec::with_capacity(aLength + bLength - 1);
for i in 0..aLength {
//for (int i = 0; i < aLength; i++) {
let aCoeff = aCoefficients[i];
@@ -470,52 +473,60 @@ impl GenericGFPoly {
);
}
}
return Ok(Box::new(GenericGFPoly::new(self.field, &product)?));
return Ok(GenericGFPoly::new(self.field.clone(), &product)?);
}
pub fn multiply_with_scalar(&self, scalar: i32) -> Box<GenericGFPoly> {
pub fn multiply_with_scalar(&self, scalar: i32) -> GenericGFPoly {
if scalar == 0 {
return self.field.getZero();
return self.getZero();
}
if scalar == 1 {
return Box::new(*self);
return self.clone();
}
let size = self.coefficients.len();
let product = Vec::with_capacity(size);
let mut product = Vec::with_capacity(size);
for i in 0..size {
//for (int i = 0; i < size; i++) {
product[i] = self
.field
.multiply(self.coefficients[i], scalar.try_into().unwrap());
}
return Box::new(GenericGFPoly::new(self.field, &product).unwrap());
return GenericGFPoly::new(self.field.clone(), &product).unwrap();
}
pub fn getZero(&self) -> Self{
GenericGFPoly::new(self.field.clone(), &vec![0]).unwrap()
}
pub fn getOne(&self) -> Self{
GenericGFPoly::new(self.field.clone(), &vec![1]).unwrap()
}
pub fn multiplyByMonomial(
&self,
degree: usize,
coefficient: i32,
) -> Result<Box<GenericGFPoly>, IllegalArgumentException> {
) -> Result<GenericGFPoly, IllegalArgumentException> {
if degree < 0 {
return Err(IllegalArgumentException::new(""));
}
if coefficient == 0 {
return Ok(self.field.getZero());
return Ok(self.getZero());
}
let size = self.coefficients.len();
let product = Vec::with_capacity(size + degree);
let mut product = Vec::with_capacity(size + degree);
for i in 0..size {
//for (int i = 0; i < size; i++) {
product[i] = self.field.multiply(self.coefficients[i], coefficient);
}
return Ok(Box::new(GenericGFPoly::new(self.field, &product)?));
return Ok(GenericGFPoly::new(self.field.clone(), &product)?);
}
pub fn divide(
&self,
other: &GenericGFPoly,
) -> Result<Vec<Box<GenericGFPoly>>, IllegalArgumentException> {
) -> Result<Vec<GenericGFPoly>, IllegalArgumentException> {
if self.field != other.field {
//if (!field.equals(other.field)) {
return Err(IllegalArgumentException::new(
@@ -526,8 +537,8 @@ impl GenericGFPoly {
return Err(IllegalArgumentException::new("Divide by 0"));
}
let mut quotient = self.field.getZero();
let mut remainder = self;
let mut quotient = self.getZero();
let mut remainder = self.clone();
let denominatorLeadingTerm = other.getCoefficient(other.getDegree());
let inverseDenominatorLeadingTerm = match self.field.inverse(denominatorLeadingTerm) {
@@ -543,11 +554,11 @@ impl GenericGFPoly {
);
let term = other.multiplyByMonomial(degreeDifference, scale)?;
let iterationQuotient = self.field.buildMonomial(degreeDifference, scale);
quotient = quotient.addOrSubtract(iterationQuotient)?;
remainder = &*remainder.addOrSubtract(term)?;
quotient = quotient.addOrSubtract(&iterationQuotient)?;
remainder = remainder.addOrSubtract(&term)?;
}
return Ok(vec![quotient, Box::new(*remainder)]);
return Ok(vec![quotient, remainder]);
}
}
@@ -556,10 +567,10 @@ impl fmt::Display for GenericGFPoly {
if self.isZero() {
return write!(f, "0");
}
let result = String::with_capacity(8 * self.getDegree());
let mut result = String::with_capacity(8 * self.getDegree());
for degree in (0..self.getDegree()).rev() {
//for (int degree = getDegree(); degree >= 0; degree--) {
let coefficient = self.getCoefficient(degree);
let mut coefficient = self.getCoefficient(degree);
if coefficient != 0 {
if coefficient < 0 {
if degree == self.getDegree() {
@@ -567,23 +578,23 @@ impl fmt::Display for GenericGFPoly {
} else {
result.push_str(" - ");
}
//coefficient = -coefficient;
todo!("probably coefficient should be unsigned but what a mess");
coefficient = -coefficient;
//todo!("probably coefficient should be unsigned but what a mess");
} else {
if result.len() > 0 {
result.push_str(" + ");
}
}
if degree == 0 || coefficient != 1 {
let alphaPower = self.field.log(coefficient);
if alphaPower.unwrap() == 0 {
if let Ok(alphaPower) = self.field.log(coefficient){
if alphaPower == 0 {
result.push_str("1");
} else if alphaPower.unwrap() == 1 {
} else if alphaPower == 1 {
result.push_str("a");
} else {
result.push_str("a^");
result.push_str(&format!("{}", alphaPower.unwrap()));
}
result.push_str(&format!("{}", alphaPower));
}}
}
if degree != 0 {
if degree == 1 {
@@ -639,13 +650,13 @@ impl fmt::Display for GenericGFPoly {
* @author sanfordsquires
*/
pub struct ReedSolomonDecoder {
field: Box<GenericGF>,
field: GenericGF,
}
impl ReedSolomonDecoder {
pub fn new(field: GenericGF) -> Self {
Self {
field: Box::new(field),
field: field,
}
}
@@ -659,18 +670,19 @@ impl ReedSolomonDecoder {
* @throws ReedSolomonException if decoding fails for any reason
*/
pub fn decode(&self, received: &mut Vec<i32>, twoS: i32) -> Result<(), ReedSolomonException> {
let poly = GenericGFPoly::new(self.field, received);
let syndromeCoefficients = Vec::with_capacity(twoS.try_into().unwrap());
let poly = GenericGFPoly::new(self.field.clone(), received).unwrap();
let mut syndromeCoefficients = Vec::with_capacity(twoS.try_into().unwrap());
let mut noError = true;
for i in 0..twoS {
//for (int i = 0; i < twoS; i++) {
let eval = poly.unwrap().evaluateAt(
let eval = poly.evaluateAt(
self.field
.exp(i + self.field.getGeneratorBase())
.try_into()
.unwrap(),
);
syndromeCoefficients[syndromeCoefficients.len() - 1 - i as usize] = eval;
let len = syndromeCoefficients.len();
syndromeCoefficients[len - 1 - i as usize] = eval;
if eval != 0 {
noError = false;
}
@@ -678,17 +690,17 @@ impl ReedSolomonDecoder {
if noError {
return Ok(());
}
let syndrome = match GenericGFPoly::new(self.field, &syndromeCoefficients) {
let syndrome = match GenericGFPoly::new(self.field.clone(), &syndromeCoefficients) {
Ok(res) => res,
Err(fail) => return Err(ReedSolomonException::new("IllegalArgumentException")),
};
let sigmaOmega = self.runEuclideanAlgorithm(
self.field.buildMonomial(twoS.try_into().unwrap(), 1),
Box::new(syndrome),
&self.field.buildMonomial(twoS.try_into().unwrap(), 1),
&syndrome,
twoS.try_into().unwrap(),
);
let sigma = sigmaOmega?[0];
let omega = sigmaOmega?[1];
)?;
let sigma = &sigmaOmega[0];
let omega = &sigmaOmega[1];
let errorLocations = self.findErrorLocations(&sigma)?;
let errorMagnitudes = self.findErrorMagnitudes(&omega, &errorLocations);
for i in 0..errorLocations.len() {
@@ -709,21 +721,25 @@ impl ReedSolomonDecoder {
fn runEuclideanAlgorithm(
&self,
a: Box<GenericGFPoly>,
b: Box<GenericGFPoly>,
a: &GenericGFPoly,
b: &GenericGFPoly,
R: usize,
) -> Result<Vec<GenericGFPoly>, ReedSolomonException> {
// Assume a's degree is >= b's
let mut a = a;
let mut b = b;
if a.getDegree() < b.getDegree() {
let temp = a;
a = b;
b = temp;
}
let rLast = a;
let r = b;
let tLast = self.field.getZero();
let t = self.field.getOne();
let mut rLast = a;
let mut r = b;
// let tLast = self.field.getZero();
// let t = self.field.getOne();
let mut tLast = a.getZero();
let mut t = a.getOne();
// Run Euclidean algorithm until r's degree is less than R/2
while 2 * r.getDegree() >= R {
@@ -738,7 +754,7 @@ impl ReedSolomonDecoder {
return Err(ReedSolomonException::new("r_{i-1} was zero"));
}
r = rLastLast;
let q = self.field.getZero();
let q = a.getZero();
let denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());
let dltInverse = match self.field.inverse(denominatorLeadingTerm) {
Ok(inv) => inv,
@@ -749,15 +765,15 @@ impl ReedSolomonDecoder {
let scale = self
.field
.multiply(r.getCoefficient(r.getDegree()), dltInverse);
q = match q.addOrSubtract(self.field.buildMonomial(degreeDiff, scale)) {
q = match q.addOrSubtract(&self.field.buildMonomial(degreeDiff, scale)) {
Ok(res) => res,
Err(err) => return Err(ReedSolomonException::new("IllegalArgumentException")),
};
r = match r.addOrSubtract(match rLast.multiplyByMonomial(degreeDiff, scale) {
Ok(res) => res,
Ok(res) => &res,
Err(err) => return Err(ReedSolomonException::new("IllegalArgumentException")),
}) {
Ok(res) => res,
Ok(res) =>&res,
Err(err) => return Err(ReedSolomonException::new("IllegalArgumentException")),
};
}
@@ -766,7 +782,7 @@ impl ReedSolomonDecoder {
Ok(res) => res,
Err(err) => return Err(ReedSolomonException::new("IllegalArgumentException")),
})
.addOrSubtract(tLastLast)
.addOrSubtract(&tLastLast)
{
Ok(res) => res,
Err(err) => return Err(ReedSolomonException::new("IllegalArgumentException")),
@@ -791,7 +807,7 @@ impl ReedSolomonDecoder {
};
let sigma = t.multiply_with_scalar(inverse);
let omega = r.multiply_with_scalar(inverse);
return Ok(vec![*sigma, *omega]);
return Ok(vec![sigma, omega]);
}
fn findErrorLocations(
@@ -898,12 +914,12 @@ impl ReedSolomonDecoder {
* @author William Rucklidge
*/
pub struct ReedSolomonEncoder {
field: Box<GenericGF>,
field: GenericGF,
cachedGenerators: Vec<GenericGFPoly>,
}
impl ReedSolomonEncoder {
pub fn new(field: Box<GenericGF>) -> Self {
pub fn new(field: GenericGF) -> Self {
Self {
field: field,
cachedGenerators: vec![GenericGFPoly::new(field, &vec![1]).unwrap()],
@@ -918,7 +934,7 @@ impl ReedSolomonEncoder {
.unwrap();
for d in self.cachedGenerators.len()..=degree {
//for (int d = cachedGenerators.size(); d <= degree; d++) {
let nextGenerator = *lastGenerator
let nextGenerator = lastGenerator
.multiply(
&GenericGFPoly::new(
self.field,
@@ -950,11 +966,11 @@ impl ReedSolomonEncoder {
return Err(IllegalArgumentException::new("No data bytes provided"));
}
let generator = self.buildGenerator(ecBytes);
let infoCoefficients: Vec<i32> = Vec::with_capacity(dataBytes);
let mut infoCoefficients: Vec<i32> = Vec::with_capacity(dataBytes);
infoCoefficients[0..dataBytes].clone_from_slice(&toEncode[0..dataBytes]);
//System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes);
let info = GenericGFPoly::new(self.field, &infoCoefficients)?;
info = *info.multiplyByMonomial(ecBytes.try_into().unwrap(), 1)?;
let mut info = GenericGFPoly::new(self.field.clone(), &infoCoefficients)?;
info = info.multiplyByMonomial(ecBytes.try_into().unwrap(), 1)?;
let remainder = info.divide(&generator)?[1];
let coefficients = remainder.getCoefficients();
let numZeroCoefficients = ecBytes - coefficients.len();