mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-28 05:12:34 +00:00
rs all tests pass
This commit is contained in:
@@ -35,15 +35,11 @@ const DECODER_RANDOM_TEST_ITERATIONS: i32 = 3;
|
|||||||
const DECODER_TEST_ITERATIONS: i32 = 10;
|
const DECODER_TEST_ITERATIONS: i32 = 10;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testDataMatrix() {
|
fn test_data_matrix() {
|
||||||
let dm256 = super::get_predefined_genericgf(super::PredefinedGenericGF::DataMatrixField256);
|
let dm256 = super::get_predefined_genericgf(super::PredefinedGenericGF::DataMatrixField256);
|
||||||
// real life test cases
|
// real life test cases
|
||||||
testEncodeDecode(
|
test_encode_decode(&dm256, &vec![142, 164, 186], &vec![114, 25, 5, 88, 102]);
|
||||||
&dm256,
|
test_encode_decode(
|
||||||
&vec![142, 164, 186],
|
|
||||||
&vec![114, 25, 5, 88, 102],
|
|
||||||
);
|
|
||||||
testEncodeDecode(
|
|
||||||
&dm256,
|
&dm256,
|
||||||
&vec![
|
&vec![
|
||||||
0x69, 0x75, 0x75, 0x71, 0x3B, 0x30, 0x30, 0x64, 0x70, 0x65, 0x66, 0x2F, 0x68, 0x70,
|
0x69, 0x75, 0x75, 0x71, 0x3B, 0x30, 0x30, 0x64, 0x70, 0x65, 0x66, 0x2F, 0x68, 0x70,
|
||||||
@@ -56,16 +52,16 @@ fn testDataMatrix() {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
// synthetic test cases
|
// synthetic test cases
|
||||||
testEncodeDecodeRandom(dm256.clone(), 10, 240);
|
test_encode_decode_random(dm256.clone(), 220, 35);
|
||||||
testEncodeDecodeRandom(dm256.clone(), 128, 127);
|
test_encode_decode_random(dm256.clone(), 10, 240);
|
||||||
testEncodeDecodeRandom(dm256.clone(), 220, 35);
|
test_encode_decode_random(dm256.clone(), 128, 127);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testQRCode() {
|
fn test_qr_code() {
|
||||||
let qrcf256 = super::get_predefined_genericgf(super::PredefinedGenericGF::QrCodeField256);
|
let qrcf256 = super::get_predefined_genericgf(super::PredefinedGenericGF::QrCodeField256);
|
||||||
// Test case from example given in ISO 18004, Annex I
|
// Test case from example given in ISO 18004, Annex I
|
||||||
testEncodeDecode(
|
test_encode_decode(
|
||||||
&qrcf256,
|
&qrcf256,
|
||||||
&vec![
|
&vec![
|
||||||
0x10, 0x20, 0x0C, 0x56, 0x61, 0x80, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11,
|
0x10, 0x20, 0x0C, 0x56, 0x61, 0x80, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11,
|
||||||
@@ -73,7 +69,7 @@ fn testQRCode() {
|
|||||||
],
|
],
|
||||||
&vec![0xA5, 0x24, 0xD4, 0xC1, 0xED, 0x36, 0xC7, 0x87, 0x2C, 0x55],
|
&vec![0xA5, 0x24, 0xD4, 0xC1, 0xED, 0x36, 0xC7, 0x87, 0x2C, 0x55],
|
||||||
);
|
);
|
||||||
testEncodeDecode(
|
test_encode_decode(
|
||||||
&qrcf256,
|
&qrcf256,
|
||||||
&vec![
|
&vec![
|
||||||
0x72, 0x67, 0x2F, 0x77, 0x69, 0x6B, 0x69, 0x2F, 0x4D, 0x61, 0x69, 0x6E, 0x5F, 0x50,
|
0x72, 0x67, 0x2F, 0x77, 0x69, 0x6B, 0x69, 0x2F, 0x4D, 0x61, 0x69, 0x6E, 0x5F, 0x50,
|
||||||
@@ -87,36 +83,36 @@ fn testQRCode() {
|
|||||||
);
|
);
|
||||||
// real life test cases
|
// real life test cases
|
||||||
// synthetic test cases
|
// synthetic test cases
|
||||||
testEncodeDecodeRandom(qrcf256.clone(), 10, 240);
|
test_encode_decode_random(qrcf256.clone(), 10, 240);
|
||||||
testEncodeDecodeRandom(qrcf256.clone(), 128, 127);
|
test_encode_decode_random(qrcf256.clone(), 128, 127);
|
||||||
testEncodeDecodeRandom(qrcf256.clone(), 220, 35);
|
test_encode_decode_random(qrcf256.clone(), 220, 35);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn testAztec() {
|
fn test_aztec() {
|
||||||
// real life test cases
|
// real life test cases
|
||||||
testEncodeDecode(
|
test_encode_decode(
|
||||||
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecParam),
|
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecParam),
|
||||||
&vec![0x5, 0x6],
|
&vec![0x5, 0x6],
|
||||||
&vec![0x3, 0x2, 0xB, 0xB, 0x7],
|
&vec![0x3, 0x2, 0xB, 0xB, 0x7],
|
||||||
);
|
);
|
||||||
testEncodeDecode(
|
test_encode_decode(
|
||||||
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecParam),
|
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecParam),
|
||||||
&vec![0x0, 0x0, 0x0, 0x9],
|
&vec![0x0, 0x0, 0x0, 0x9],
|
||||||
&vec![0xA, 0xD, 0x8, 0x6, 0x5, 0x6],
|
&vec![0xA, 0xD, 0x8, 0x6, 0x5, 0x6],
|
||||||
);
|
);
|
||||||
testEncodeDecode(
|
test_encode_decode(
|
||||||
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecParam),
|
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecParam),
|
||||||
&vec![0x2, 0x8, 0x8, 0x7],
|
&vec![0x2, 0x8, 0x8, 0x7],
|
||||||
&vec![0xE, 0xC, 0xA, 0x9, 0x6, 0x8],
|
&vec![0xE, 0xC, 0xA, 0x9, 0x6, 0x8],
|
||||||
);
|
);
|
||||||
testEncodeDecode(
|
test_encode_decode(
|
||||||
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData6),
|
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData6),
|
||||||
&vec![0x9, 0x32, 0x1, 0x29, 0x2F, 0x2, 0x27, 0x25, 0x1, 0x1B],
|
&vec![0x9, 0x32, 0x1, 0x29, 0x2F, 0x2, 0x27, 0x25, 0x1, 0x1B],
|
||||||
&vec![0x2C, 0x2, 0xD, 0xD, 0xA, 0x16, 0x28, 0x9, 0x22, 0xA, 0x14],
|
&vec![0x2C, 0x2, 0xD, 0xD, 0xA, 0x16, 0x28, 0x9, 0x22, 0xA, 0x14],
|
||||||
);
|
);
|
||||||
|
|
||||||
testEncodeDecode(
|
test_encode_decode(
|
||||||
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData8),
|
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData8),
|
||||||
&vec![
|
&vec![
|
||||||
0xE0, 0x86, 0x42, 0x98, 0xE8, 0x4A, 0x96, 0xC6, 0xB9, 0xF0, 0x8C, 0xA7, 0x4A, 0xDA,
|
0xE0, 0x86, 0x42, 0x98, 0xE8, 0x4A, 0x96, 0xC6, 0xB9, 0xF0, 0x8C, 0xA7, 0x4A, 0xDA,
|
||||||
@@ -132,7 +128,7 @@ fn testAztec() {
|
|||||||
0x29, 0xFE, 0x06, 0x49, 0xF3, 0x73, 0x9F, 0xC1, 0x75,
|
0x29, 0xFE, 0x06, 0x49, 0xF3, 0x73, 0x9F, 0xC1, 0x75,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
testEncodeDecode(
|
test_encode_decode(
|
||||||
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData10),
|
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData10),
|
||||||
&vec![
|
&vec![
|
||||||
0x15C, 0x1E1, 0x2D5, 0x02E, 0x048, 0x1E2, 0x037, 0x0CD, 0x02E, 0x056, 0x26A, 0x281,
|
0x15C, 0x1E1, 0x2D5, 0x02E, 0x048, 0x1E2, 0x037, 0x0CD, 0x02E, 0x056, 0x26A, 0x281,
|
||||||
@@ -179,7 +175,7 @@ fn testAztec() {
|
|||||||
0x02E, 0x35A, 0x0E4, 0x2E9, 0x17A, 0x166, 0x03C, 0x007,
|
0x02E, 0x35A, 0x0E4, 0x2E9, 0x17A, 0x166, 0x03C, 0x007,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
testEncodeDecode(
|
test_encode_decode(
|
||||||
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData12),
|
&super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData12),
|
||||||
&vec![
|
&vec![
|
||||||
0x571, 0xE1B, 0x542, 0xE12, 0x1E2, 0x0DC, 0xCD0, 0xB85, 0x69A, 0xA81, 0x709, 0xA6A,
|
0x571, 0xE1B, 0x542, 0xE12, 0x1E2, 0x0DC, 0xCD0, 0xB85, 0x69A, 0xA81, 0x709, 0xA6A,
|
||||||
@@ -333,15 +329,15 @@ fn testAztec() {
|
|||||||
let azd10 = super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData10);
|
let azd10 = super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData10);
|
||||||
let azd12 = super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData12);
|
let azd12 = super::get_predefined_genericgf(super::PredefinedGenericGF::AztecData12);
|
||||||
|
|
||||||
testEncodeDecodeRandom(azp.clone(), 2, 5); // compact mode message
|
test_encode_decode_random(azp.clone(), 2, 5); // compact mode message
|
||||||
testEncodeDecodeRandom(azp.clone(), 4, 6); // full mode message
|
test_encode_decode_random(azp.clone(), 4, 6); // full mode message
|
||||||
testEncodeDecodeRandom(azd6.clone(), 10, 7);
|
test_encode_decode_random(azd6.clone(), 10, 7);
|
||||||
testEncodeDecodeRandom(azd6.clone(), 20, 12);
|
test_encode_decode_random(azd6.clone(), 20, 12);
|
||||||
testEncodeDecodeRandom(azd8.clone(), 20, 11);
|
test_encode_decode_random(azd8.clone(), 20, 11);
|
||||||
testEncodeDecodeRandom(azd8.clone(), 128, 127);
|
test_encode_decode_random(azd8.clone(), 128, 127);
|
||||||
testEncodeDecodeRandom(azd10.clone(), 128, 128);
|
test_encode_decode_random(azd10.clone(), 128, 128);
|
||||||
testEncodeDecodeRandom(azd10.clone(), 768, 255);
|
test_encode_decode_random(azd10.clone(), 768, 255);
|
||||||
testEncodeDecodeRandom(azd12.clone(), 3072, 1023);
|
test_encode_decode_random(azd12.clone(), 3072, 1023);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn corrupt(received: &mut Vec<i32>, howMany: i32, random: &mut rand::rngs::ThreadRng, max: i32) {
|
fn corrupt(received: &mut Vec<i32>, howMany: i32, random: &mut rand::rngs::ThreadRng, max: i32) {
|
||||||
@@ -365,7 +361,7 @@ fn corrupt(received: &mut Vec<i32>, howMany: i32, random: &mut rand::rngs::Threa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testEncodeDecodeRandom(field: GenericGF, dataSize: usize, ecSize: usize) {
|
fn test_encode_decode_random(field: GenericGF, dataSize: usize, ecSize: usize) {
|
||||||
assert!(
|
assert!(
|
||||||
dataSize > 0 && dataSize <= field.getSize() - 3,
|
dataSize > 0 && dataSize <= field.getSize() - 3,
|
||||||
"Invalid data size for {}",
|
"Invalid data size for {}",
|
||||||
@@ -377,10 +373,10 @@ fn testEncodeDecodeRandom(field: GenericGF, dataSize: usize, ecSize: usize) {
|
|||||||
field
|
field
|
||||||
);
|
);
|
||||||
let mut encoder = ReedSolomonEncoder::new(field.clone());
|
let mut encoder = ReedSolomonEncoder::new(field.clone());
|
||||||
let mut message = Vec::with_capacity(dataSize + ecSize);
|
let mut message = vec![0; dataSize + ecSize];
|
||||||
let mut dataWords: Vec<i32> = Vec::with_capacity(dataSize);
|
let mut dataWords: Vec<i32> = vec![0; dataSize];
|
||||||
let mut ecWords = Vec::with_capacity(ecSize);
|
let mut ecWords = vec![0; ecSize];
|
||||||
let mut random = getPseudoRandom();
|
let mut random = get_pseudo_random();
|
||||||
let iterations = if field.getSize() > 256 {
|
let iterations = if field.getSize() > 256 {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
@@ -396,31 +392,34 @@ fn testEncodeDecodeRandom(field: GenericGF, dataSize: usize, ecSize: usize) {
|
|||||||
// generate ECC words
|
// generate ECC words
|
||||||
message[0..dataWords.len()].clone_from_slice(&dataWords[..]);
|
message[0..dataWords.len()].clone_from_slice(&dataWords[..]);
|
||||||
//System.arraycopy(dataWords, 0, message, 0, dataWords.len());
|
//System.arraycopy(dataWords, 0, message, 0, dataWords.len());
|
||||||
encoder.encode(&mut message, ecWords.len());
|
if let Err(err) = encoder.encode(&mut message, ecWords.len()){
|
||||||
ecWords[0..ecSize].clone_from_slice(&message[dataSize..ecSize]);
|
panic!("{:#?}", err);
|
||||||
|
}
|
||||||
|
ecWords[0..ecSize].clone_from_slice(&message[dataSize..dataSize + ecSize]);
|
||||||
//System.arraycopy(message, dataSize, ecWords, 0, ecSize);
|
//System.arraycopy(message, dataSize, ecWords, 0, ecSize);
|
||||||
// check to see if Decoder can fix up to ecWords/2 random errors
|
// check to see if Decoder can fix up to ecWords/2 random errors
|
||||||
testDecoder(&field, &dataWords, &ecWords);
|
test_decoder(&field, &dataWords, &ecWords);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testEncodeDecode(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
|
fn test_encode_decode(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
|
||||||
testEncoder(field, dataWords, ecWords);
|
test_encoder(field, dataWords, ecWords);
|
||||||
testDecoder(field, dataWords, ecWords);
|
test_decoder(field, dataWords, ecWords);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testEncoder(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
|
fn test_encoder(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
|
||||||
let mut encoder = ReedSolomonEncoder::new(field.clone());
|
let mut encoder = ReedSolomonEncoder::new(field.clone());
|
||||||
let mut messageExpected = vec![0;dataWords.len() + ecWords.len()];//Vec::with_capacity(dataWords.len() + ecWords.len());
|
let mut messageExpected = vec![0; dataWords.len() + ecWords.len()];
|
||||||
let mut message = vec![0;dataWords.len() + ecWords.len()];//Vec::with_capacity(dataWords.len() + ecWords.len());
|
let mut message = vec![0; dataWords.len() + ecWords.len()];
|
||||||
messageExpected[0..dataWords.len()].clone_from_slice(&dataWords[0..dataWords.len()]);
|
messageExpected[0..dataWords.len()].clone_from_slice(&dataWords[0..dataWords.len()]);
|
||||||
//System.arraycopy(dataWords, 0, messageExpected, 0, dataWords.len());
|
//System.arraycopy(dataWords, 0, messageExpected, 0, dataWords.len());
|
||||||
messageExpected[dataWords.len()..ecWords.len()+dataWords.len()].clone_from_slice(&ecWords[..ecWords.len()]);
|
messageExpected[dataWords.len()..ecWords.len() + dataWords.len()]
|
||||||
|
.clone_from_slice(&ecWords[..ecWords.len()]);
|
||||||
//System.arraycopy(ecWords, 0, messageExpected, dataWords.len(), ecWords.len());
|
//System.arraycopy(ecWords, 0, messageExpected, dataWords.len(), ecWords.len());
|
||||||
message[0..dataWords.len()].clone_from_slice(&dataWords[0..dataWords.len()]);
|
message[0..dataWords.len()].clone_from_slice(&dataWords[0..dataWords.len()]);
|
||||||
//System.arraycopy(dataWords, 0, message, 0, dataWords.len());
|
//System.arraycopy(dataWords, 0, message, 0, dataWords.len());
|
||||||
encoder.encode(&mut message, ecWords.len());
|
encoder.encode(&mut message, ecWords.len());
|
||||||
assertDataEquals(
|
assert_data_equals(
|
||||||
format!(
|
format!(
|
||||||
"Encode in {} ({},{}) failed",
|
"Encode in {} ({},{}) failed",
|
||||||
field,
|
field,
|
||||||
@@ -432,11 +431,11 @@ fn testEncoder(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn testDecoder(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
|
fn test_decoder(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
|
||||||
let decoder = ReedSolomonDecoder::new(field.clone());
|
let decoder = ReedSolomonDecoder::new(field.clone());
|
||||||
let mut message = Vec::with_capacity(dataWords.len() + ecWords.len());
|
let mut message = vec![0; dataWords.len() + ecWords.len()];
|
||||||
let maxErrors = ecWords.len() / 2;
|
let maxErrors = ecWords.len() / 2;
|
||||||
let mut random = getPseudoRandom();
|
let mut random = get_pseudo_random();
|
||||||
let iterations = if field.getSize() > 256 {
|
let iterations = if field.getSize() > 256 {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
@@ -444,15 +443,28 @@ fn testDecoder(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
|
|||||||
};
|
};
|
||||||
for _j in 0..iterations {
|
for _j in 0..iterations {
|
||||||
//for (int j = 0; j < iterations; j++) {
|
//for (int j = 0; j < iterations; j++) {
|
||||||
|
let mut skip_count = 0;
|
||||||
|
let mut skipping = false;
|
||||||
for mut i in 0..ecWords.len() {
|
for mut i in 0..ecWords.len() {
|
||||||
//for (int i = 0; i < ecWords.length; i++) {
|
//for (int i = 0; i < ecWords.length; i++) {
|
||||||
if i > 10 && i < ecWords.len() / 2 - 10 {
|
if i > 10 && ecWords.len() / 2 > 11 && i < ecWords.len() / 2 - 10 {
|
||||||
// performance improvement - skip intermediate cases in long-running tests
|
// performance improvement - skip intermediate cases in long-running tests
|
||||||
i += ecWords.len() / 10;
|
// i += ecWords.len() / 10;
|
||||||
|
skipping = true;
|
||||||
|
skip_count += 1;
|
||||||
|
}
|
||||||
|
if skipping {
|
||||||
|
if skip_count > ecWords.len() / 10 {
|
||||||
|
skipping = false;
|
||||||
|
skip_count = 0;
|
||||||
|
}else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
message[0..dataWords.len()].clone_from_slice(&dataWords[0..dataWords.len()]);
|
message[0..dataWords.len()].clone_from_slice(&dataWords[0..dataWords.len()]);
|
||||||
//System.arraycopy(dataWords, 0, message, 0, dataWords.len());
|
//System.arraycopy(dataWords, 0, message, 0, dataWords.len());
|
||||||
message[dataWords.len()..ecWords.len()].clone_from_slice(&ecWords[0..dataWords.len()]);
|
message[dataWords.len()..ecWords.len() + dataWords.len()]
|
||||||
|
.clone_from_slice(&ecWords[0..ecWords.len()]);
|
||||||
//System.arraycopy(ecWords, 0, message, dataWords.len(), ecWords.len());
|
//System.arraycopy(ecWords, 0, message, dataWords.len(), ecWords.len());
|
||||||
corrupt(
|
corrupt(
|
||||||
&mut message,
|
&mut message,
|
||||||
@@ -490,7 +502,7 @@ fn testDecoder(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
|
|||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
if i < maxErrors {
|
if i < maxErrors {
|
||||||
assertDataEquals(
|
assert_data_equals(
|
||||||
format!(
|
format!(
|
||||||
"Decode in {} ({},{}) failed at {} errors",
|
"Decode in {} ({},{}) failed at {} errors",
|
||||||
field,
|
field,
|
||||||
@@ -506,7 +518,7 @@ fn testDecoder(field: &GenericGF, dataWords: &Vec<i32>, ecWords: &Vec<i32>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assertDataEquals(message: String, expected: &Vec<i32>, received: &Vec<i32>) {
|
fn assert_data_equals(message: String, expected: &Vec<i32>, received: &Vec<i32>) {
|
||||||
for i in 0..expected.len() {
|
for i in 0..expected.len() {
|
||||||
//for (int i = 0; i < expected.length; i++) {
|
//for (int i = 0; i < expected.length; i++) {
|
||||||
if expected[i] != received[i] {
|
if expected[i] != received[i] {
|
||||||
@@ -514,15 +526,15 @@ fn assertDataEquals(message: String, expected: &Vec<i32>, received: &Vec<i32>) {
|
|||||||
"{}. Mismatch at {}. Expected {}, got {}",
|
"{}. Mismatch at {}. Expected {}, got {}",
|
||||||
message,
|
message,
|
||||||
i,
|
i,
|
||||||
arrayToString(&expected),
|
array_to_string(&expected),
|
||||||
arrayToString(&received[0..expected.len()])
|
array_to_string(&received[0..expected.len()])
|
||||||
);
|
);
|
||||||
//fail();
|
//fail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn arrayToString(data: &[i32]) -> String {
|
fn array_to_string(data: &[i32]) -> String {
|
||||||
let mut sb = String::from("{");
|
let mut sb = String::from("{");
|
||||||
for i in 0..data.len() {
|
for i in 0..data.len() {
|
||||||
//for (int i = 0; i < data.length; i++) {
|
//for (int i = 0; i < data.length; i++) {
|
||||||
@@ -534,7 +546,7 @@ fn arrayToString(data: &[i32]) -> String {
|
|||||||
sb
|
sb
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getPseudoRandom() -> rand::rngs::ThreadRng {
|
fn get_pseudo_random() -> rand::rngs::ThreadRng {
|
||||||
rand::thread_rng()
|
rand::thread_rng()
|
||||||
//return new Random(0xDEADBEEF);
|
//return new Random(0xDEADBEEF);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ pub enum PredefinedGenericGF {
|
|||||||
QrCodeField256,
|
QrCodeField256,
|
||||||
DataMatrixField256,
|
DataMatrixField256,
|
||||||
AztecData8,
|
AztecData8,
|
||||||
MaxicodeField64
|
MaxicodeField64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replacement for old const options, has the downside of generating new versions whenever one is requested.
|
/// Replacement for old const options, has the downside of generating new versions whenever one is requested.
|
||||||
@@ -51,10 +51,14 @@ pub fn get_predefined_genericgf(request:PredefinedGenericGF) -> GenericGF {
|
|||||||
match request {
|
match request {
|
||||||
PredefinedGenericGF::AztecData12 => GenericGF::new(0x1069, 4096, 1), // x^12 + x^6 + x^5 + x^3 + 1,
|
PredefinedGenericGF::AztecData12 => GenericGF::new(0x1069, 4096, 1), // x^12 + x^6 + x^5 + x^3 + 1,
|
||||||
PredefinedGenericGF::AztecData10 => GenericGF::new(0x409, 1024, 1), // x^10 + x^3 + 1
|
PredefinedGenericGF::AztecData10 => GenericGF::new(0x409, 1024, 1), // x^10 + x^3 + 1
|
||||||
PredefinedGenericGF::AztecData6 | PredefinedGenericGF::MaxicodeField64 => GenericGF::new(0x43, 64, 1), // x^6 + x + 1
|
PredefinedGenericGF::AztecData6 | PredefinedGenericGF::MaxicodeField64 => {
|
||||||
|
GenericGF::new(0x43, 64, 1)
|
||||||
|
} // x^6 + x + 1
|
||||||
PredefinedGenericGF::AztecParam => GenericGF::new(0x13, 16, 1), // x^4 + x + 1
|
PredefinedGenericGF::AztecParam => GenericGF::new(0x13, 16, 1), // x^4 + x + 1
|
||||||
PredefinedGenericGF::QrCodeField256 => GenericGF::new(0x011D, 256, 0), // x^8 + x^4 + x^3 + x^2 + 1
|
PredefinedGenericGF::QrCodeField256 => GenericGF::new(0x011D, 256, 0), // x^8 + x^4 + x^3 + x^2 + 1
|
||||||
PredefinedGenericGF::DataMatrixField256 | PredefinedGenericGF::AztecData8 => GenericGF::new(0x012D, 256, 1), // x^8 + x^5 + x^3 + x^2 + 1
|
PredefinedGenericGF::DataMatrixField256 | PredefinedGenericGF::AztecData8 => {
|
||||||
|
GenericGF::new(0x012D, 256, 1)
|
||||||
|
} // x^8 + x^5 + x^3 + x^2 + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,10 +109,10 @@ impl GenericGF {
|
|||||||
* In most cases it should be 1, but for QR code it is 0.
|
* In most cases it should be 1, but for QR code it is 0.
|
||||||
*/
|
*/
|
||||||
pub fn new(primitive: i32, size: usize, b: i32) -> Self {
|
pub fn new(primitive: i32, size: usize, b: i32) -> Self {
|
||||||
let mut expTable = vec![0;size];//Vec::with_capacity(size);
|
let mut expTable = vec![0; size];
|
||||||
let mut logTable = vec![0;size];//Vec::with_capacity(size);
|
let mut logTable = vec![0; size];
|
||||||
let mut x = 1;
|
let mut x = 1;
|
||||||
for i in 0..size-1 {
|
for i in 0..size {
|
||||||
//for (int i = 0; i < size; i++) {
|
//for (int i = 0; i < size; i++) {
|
||||||
//expTable.push(x);
|
//expTable.push(x);
|
||||||
expTable[i] = x;
|
expTable[i] = x;
|
||||||
@@ -119,11 +123,28 @@ impl GenericGF {
|
|||||||
x &= sz_m_1;
|
x &= sz_m_1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i in 0..size {
|
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].try_into().unwrap();
|
||||||
logTable[loc] = i.try_into().unwrap();
|
logTable[loc] = i.try_into().unwrap();
|
||||||
}
|
}
|
||||||
|
logTable[0] = 0;
|
||||||
|
|
||||||
|
// let mut p:u32;
|
||||||
|
// //int i;
|
||||||
|
// /*Initialize the table of powers of a primtive root, alpha=0x02.*/
|
||||||
|
// p = 1;
|
||||||
|
// for i in 0..size {
|
||||||
|
// // for (i = 0; i < 256; i++) {
|
||||||
|
// expTable[i] = expTable[i + size - 1] = p;
|
||||||
|
// p = ((p << 1) ^ (-(p as i32 >> 7) & primitive) as u32) & 0xFF;
|
||||||
|
// }
|
||||||
|
// /*Invert the table to recover the logs.*/
|
||||||
|
// for i in 0..size-1 {
|
||||||
|
// // for (i = 0; i < 255; i++)
|
||||||
|
// logTable[expTable[i].try_into().unwrap()] = i;
|
||||||
|
// /*Note that we rely on the fact that _gf->log[0]=0 below.*/
|
||||||
|
logTable[0] = 0;
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
expTable,
|
expTable,
|
||||||
@@ -155,7 +176,7 @@ impl GenericGF {
|
|||||||
if coefficient == 0 {
|
if coefficient == 0 {
|
||||||
return GenericGFPoly::new(self.clone(), &vec![0]).unwrap();
|
return GenericGFPoly::new(self.clone(), &vec![0]).unwrap();
|
||||||
}
|
}
|
||||||
let mut coefficients = vec![0;degree+1];//Vec::with_capacity(degree + 1);
|
let mut coefficients = vec![0; degree + 1];
|
||||||
coefficients[0] = coefficient;
|
coefficients[0] = coefficient;
|
||||||
return GenericGFPoly::new(self.clone(), &coefficients).unwrap();
|
return GenericGFPoly::new(self.clone(), &coefficients).unwrap();
|
||||||
}
|
}
|
||||||
@@ -282,12 +303,11 @@ impl GenericGFPoly {
|
|||||||
* or if leading coefficient is 0 and this is not a
|
* or if leading coefficient is 0 and this is not a
|
||||||
* constant polynomial (that is, it is not the monomial "0")
|
* constant polynomial (that is, it is not the monomial "0")
|
||||||
*/
|
*/
|
||||||
pub fn new(
|
pub fn new(field: GenericGF, coefficients: &Vec<i32>) -> Result<Self, Exceptions> {
|
||||||
field: GenericGF,
|
|
||||||
coefficients: &Vec<i32>,
|
|
||||||
) -> Result<Self, Exceptions> {
|
|
||||||
if coefficients.len() == 0 {
|
if coefficients.len() == 0 {
|
||||||
return Err(Exceptions::IllegalArgumentException("coefficients.len()".to_owned()));
|
return Err(Exceptions::IllegalArgumentException(
|
||||||
|
"coefficients.len()".to_owned(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
field: field,
|
field: field,
|
||||||
@@ -302,10 +322,9 @@ impl GenericGFPoly {
|
|||||||
if firstNonZero == coefficientsLength {
|
if firstNonZero == coefficientsLength {
|
||||||
vec![0]
|
vec![0]
|
||||||
} else {
|
} else {
|
||||||
let mut new_coefficients =
|
let mut new_coefficients = vec![0; coefficientsLength - firstNonZero];
|
||||||
Vec::with_capacity(coefficientsLength - firstNonZero);
|
let l = new_coefficients.len() - 1;
|
||||||
let l = new_coefficients.len();
|
new_coefficients[0..=l].clone_from_slice(&coefficients[firstNonZero..]);
|
||||||
new_coefficients[0..l].clone_from_slice(&coefficients[firstNonZero..l]);
|
|
||||||
// System.arraycopy(coefficients,
|
// System.arraycopy(coefficients,
|
||||||
// firstNonZero,
|
// firstNonZero,
|
||||||
// this.coefficients,
|
// this.coefficients,
|
||||||
@@ -377,10 +396,7 @@ impl GenericGFPoly {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn addOrSubtract(
|
pub fn addOrSubtract(&self, other: &GenericGFPoly) -> Result<GenericGFPoly, Exceptions> {
|
||||||
&self,
|
|
||||||
other: &GenericGFPoly,
|
|
||||||
) -> Result<GenericGFPoly, Exceptions> {
|
|
||||||
if self.field != other.field {
|
if self.field != other.field {
|
||||||
return Err(Exceptions::IllegalArgumentException(
|
return Err(Exceptions::IllegalArgumentException(
|
||||||
"GenericGFPolys do not have same GenericGF field".to_owned(),
|
"GenericGFPolys do not have same GenericGF field".to_owned(),
|
||||||
@@ -401,7 +417,7 @@ impl GenericGFPoly {
|
|||||||
largerCoefficients = temp;
|
largerCoefficients = temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut sumDiff = Vec::with_capacity(largerCoefficients.len());
|
let mut sumDiff = vec![0; largerCoefficients.len()];
|
||||||
let lengthDiff = largerCoefficients.len() - smallerCoefficients.len();
|
let lengthDiff = largerCoefficients.len() - smallerCoefficients.len();
|
||||||
// Copy high-order terms only found in higher-degree polynomial's coefficients
|
// Copy high-order terms only found in higher-degree polynomial's coefficients
|
||||||
sumDiff[0..lengthDiff].clone_from_slice(&largerCoefficients[0..lengthDiff]);
|
sumDiff[0..lengthDiff].clone_from_slice(&largerCoefficients[0..lengthDiff]);
|
||||||
@@ -418,10 +434,7 @@ impl GenericGFPoly {
|
|||||||
return Ok(GenericGFPoly::new(self.field.clone(), &sumDiff)?);
|
return Ok(GenericGFPoly::new(self.field.clone(), &sumDiff)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn multiply(
|
pub fn multiply(&self, other: &GenericGFPoly) -> Result<GenericGFPoly, Exceptions> {
|
||||||
&self,
|
|
||||||
other: &GenericGFPoly,
|
|
||||||
) -> Result<GenericGFPoly, Exceptions> {
|
|
||||||
if self.field != other.field {
|
if self.field != other.field {
|
||||||
//if (!field.equals(other.field)) {
|
//if (!field.equals(other.field)) {
|
||||||
return Err(Exceptions::IllegalArgumentException(
|
return Err(Exceptions::IllegalArgumentException(
|
||||||
@@ -435,7 +448,7 @@ impl GenericGFPoly {
|
|||||||
let aLength = aCoefficients.len();
|
let aLength = aCoefficients.len();
|
||||||
let bCoefficients = other.coefficients.clone();
|
let bCoefficients = other.coefficients.clone();
|
||||||
let bLength = bCoefficients.len();
|
let bLength = bCoefficients.len();
|
||||||
let mut product = vec![0;aLength + bLength - 1];//Vec::with_capacity(aLength + bLength - 1);
|
let mut product = vec![0; aLength + bLength - 1];
|
||||||
for i in 0..aLength {
|
for i in 0..aLength {
|
||||||
//for (int i = 0; i < aLength; i++) {
|
//for (int i = 0; i < aLength; i++) {
|
||||||
let aCoeff = aCoefficients[i];
|
let aCoeff = aCoefficients[i];
|
||||||
@@ -465,7 +478,7 @@ impl GenericGFPoly {
|
|||||||
}
|
}
|
||||||
let size = self.coefficients.len();
|
let size = self.coefficients.len();
|
||||||
|
|
||||||
let mut product = Vec::with_capacity(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
|
||||||
@@ -483,7 +496,7 @@ impl GenericGFPoly {
|
|||||||
GenericGFPoly::new(self.field.clone(), &vec![1]).unwrap()
|
GenericGFPoly::new(self.field.clone(), &vec![1]).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn multiplyByMonomial(
|
pub fn multiply_by_monomial(
|
||||||
&self,
|
&self,
|
||||||
degree: usize,
|
degree: usize,
|
||||||
coefficient: i32,
|
coefficient: i32,
|
||||||
@@ -495,7 +508,7 @@ impl GenericGFPoly {
|
|||||||
return Ok(self.getZero());
|
return Ok(self.getZero());
|
||||||
}
|
}
|
||||||
let size = self.coefficients.len();
|
let size = self.coefficients.len();
|
||||||
let mut product = vec![0;size+degree];//Vec::with_capacity(size + degree);
|
let mut product = vec![0; size + degree];
|
||||||
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.field.multiply(self.coefficients[i], coefficient);
|
product[i] = self.field.multiply(self.coefficients[i], coefficient);
|
||||||
@@ -506,15 +519,16 @@ impl GenericGFPoly {
|
|||||||
pub fn divide(
|
pub fn divide(
|
||||||
&self,
|
&self,
|
||||||
other: &GenericGFPoly,
|
other: &GenericGFPoly,
|
||||||
) -> Result<Vec<GenericGFPoly>, Exceptions> {
|
) -> Result<(GenericGFPoly, GenericGFPoly), Exceptions> {
|
||||||
if self.field != other.field {
|
if self.field != other.field {
|
||||||
//if (!field.equals(other.field)) {
|
|
||||||
return Err(Exceptions::IllegalArgumentException(
|
return Err(Exceptions::IllegalArgumentException(
|
||||||
"GenericGFPolys do not have same GenericGF field".to_owned(),
|
"GenericGFPolys do not have same GenericGF field".to_owned(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if other.isZero() {
|
if other.isZero() {
|
||||||
return Err(Exceptions::IllegalArgumentException("Divide by 0".to_owned()));
|
return Err(Exceptions::IllegalArgumentException(
|
||||||
|
"Divide by 0".to_owned(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut quotient = self.getZero();
|
let mut quotient = self.getZero();
|
||||||
@@ -523,22 +537,26 @@ impl GenericGFPoly {
|
|||||||
let denominator_leading_term = other.getCoefficient(other.getDegree());
|
let denominator_leading_term = other.getCoefficient(other.getDegree());
|
||||||
let inverse_denominator_leading_term = match self.field.inverse(denominator_leading_term) {
|
let inverse_denominator_leading_term = match self.field.inverse(denominator_leading_term) {
|
||||||
Ok(val) => val,
|
Ok(val) => val,
|
||||||
Err(issue) => return Err(Exceptions::IllegalArgumentException("arithmetic issue".to_owned())),
|
Err(issue) => {
|
||||||
|
return Err(Exceptions::IllegalArgumentException(
|
||||||
|
"arithmetic issue".to_owned(),
|
||||||
|
))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
while remainder.getDegree() >= other.getDegree() && !remainder.isZero() {
|
while remainder.getDegree() >= other.getDegree() && !remainder.isZero() {
|
||||||
let degreeDifference = remainder.getDegree() - other.getDegree();
|
let degree_difference = remainder.getDegree() - other.getDegree();
|
||||||
let scale = self.field.multiply(
|
let scale = self.field.multiply(
|
||||||
remainder.getCoefficient(remainder.getDegree()),
|
remainder.getCoefficient(remainder.getDegree()),
|
||||||
inverse_denominator_leading_term,
|
inverse_denominator_leading_term,
|
||||||
);
|
);
|
||||||
let term = other.multiplyByMonomial(degreeDifference, scale)?;
|
let term = other.multiply_by_monomial(degree_difference, scale)?;
|
||||||
let iterationQuotient = self.field.buildMonomial(degreeDifference, scale);
|
let iteration_quotient = self.field.buildMonomial(degree_difference, scale);
|
||||||
quotient = quotient.addOrSubtract(&iterationQuotient)?;
|
quotient = quotient.addOrSubtract(&iteration_quotient)?;
|
||||||
remainder = remainder.addOrSubtract(&term)?;
|
remainder = remainder.addOrSubtract(&term)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(vec![quotient, remainder]);
|
return Ok((quotient, remainder));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,7 +577,6 @@ impl fmt::Display for GenericGFPoly {
|
|||||||
result.push_str(" - ");
|
result.push_str(" - ");
|
||||||
}
|
}
|
||||||
coefficient = -coefficient;
|
coefficient = -coefficient;
|
||||||
//todo!("probably coefficient should be unsigned but what a mess");
|
|
||||||
} else {
|
} else {
|
||||||
if result.len() > 0 {
|
if result.len() > 0 {
|
||||||
result.push_str(" + ");
|
result.push_str(" + ");
|
||||||
@@ -650,7 +667,7 @@ 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.clone(), received).unwrap();
|
let poly = GenericGFPoly::new(self.field.clone(), received).unwrap();
|
||||||
let mut syndromeCoefficients = Vec::with_capacity(twoS.try_into().unwrap());
|
let mut syndromeCoefficients = vec![0; twoS.try_into().unwrap()];
|
||||||
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++) {
|
||||||
@@ -671,7 +688,11 @@ impl ReedSolomonDecoder {
|
|||||||
}
|
}
|
||||||
let syndrome = match GenericGFPoly::new(self.field.clone(), &syndromeCoefficients) {
|
let syndrome = match GenericGFPoly::new(self.field.clone(), &syndromeCoefficients) {
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(fail) => return Err(Exceptions::ReedSolomonException("IllegalArgumentException".to_owned())),
|
Err(fail) => {
|
||||||
|
return Err(Exceptions::ReedSolomonException(
|
||||||
|
"IllegalArgumentException".to_owned(),
|
||||||
|
))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let sigmaOmega = self.runEuclideanAlgorithm(
|
let sigmaOmega = self.runEuclideanAlgorithm(
|
||||||
&self.field.buildMonomial(twoS.try_into().unwrap(), 1),
|
&self.field.buildMonomial(twoS.try_into().unwrap(), 1),
|
||||||
@@ -684,14 +705,15 @@ 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 position = received.len()
|
let log_value = self.field.log(errorLocations[i].try_into().unwrap())?;
|
||||||
- 1
|
if log_value > received.len() as i32 - 1 {
|
||||||
- match self.field.log(errorLocations[i].try_into().unwrap()) {
|
return Ok(());
|
||||||
Ok(size) => size as usize,
|
}
|
||||||
Err(err) => return Err(Exceptions::ReedSolomonException("IllegalArgumentException".to_owned())),
|
let position: usize = received.len() - 1 - log_value as usize;
|
||||||
};
|
|
||||||
if position < 0 {
|
if position < 0 {
|
||||||
return Err(Exceptions::ReedSolomonException("Bad error location".to_owned()));
|
return Err(Exceptions::ReedSolomonException(
|
||||||
|
"Bad error location".to_owned(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
received[position] = GenericGF::addOrSubtract(received[position], errorMagnitudes[i]);
|
received[position] = GenericGF::addOrSubtract(received[position], errorMagnitudes[i]);
|
||||||
}
|
}
|
||||||
@@ -730,14 +752,20 @@ impl ReedSolomonDecoder {
|
|||||||
// Divide rLastLast by rLast, with quotient in q and remainder in r
|
// Divide rLastLast by rLast, with quotient in q and remainder in r
|
||||||
if rLast.isZero() {
|
if rLast.isZero() {
|
||||||
// Oops, Euclidean algorithm already terminated?
|
// Oops, Euclidean algorithm already terminated?
|
||||||
return Err(Exceptions::ReedSolomonException("r_{i-1} was zero".to_owned()));
|
return Err(Exceptions::ReedSolomonException(
|
||||||
|
"r_{i-1} was zero".to_owned(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
r = rLastLast;
|
r = rLastLast;
|
||||||
let mut q = r.getZero();
|
let mut q = r.getZero();
|
||||||
let denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());
|
let denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());
|
||||||
let dltInverse = match self.field.inverse(denominatorLeadingTerm) {
|
let dltInverse = match self.field.inverse(denominatorLeadingTerm) {
|
||||||
Ok(inv) => inv,
|
Ok(inv) => inv,
|
||||||
Err(err) => return Err(Exceptions::ReedSolomonException("ArithmetricException".to_owned())),
|
Err(err) => {
|
||||||
|
return Err(Exceptions::ReedSolomonException(
|
||||||
|
"ArithmetricException".to_owned(),
|
||||||
|
))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
while r.getDegree() >= rLast.getDegree() && !r.isZero() {
|
while r.getDegree() >= rLast.getDegree() && !r.isZero() {
|
||||||
let degreeDiff = r.getDegree() - rLast.getDegree();
|
let degreeDiff = r.getDegree() - rLast.getDegree();
|
||||||
@@ -746,25 +774,45 @@ impl ReedSolomonDecoder {
|
|||||||
.multiply(r.getCoefficient(r.getDegree()), dltInverse);
|
.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,
|
Ok(res) => res,
|
||||||
Err(err) => return Err(Exceptions::ReedSolomonException("IllegalArgumentException".to_owned())),
|
Err(err) => {
|
||||||
|
return Err(Exceptions::ReedSolomonException(
|
||||||
|
"IllegalArgumentException".to_owned(),
|
||||||
|
))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
r = match r.addOrSubtract(&match rLast.multiplyByMonomial(degreeDiff, scale) {
|
r = match r.addOrSubtract(&match rLast.multiply_by_monomial(degreeDiff, scale) {
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(err) => return Err(Exceptions::ReedSolomonException("IllegalArgumentException".to_owned())),
|
Err(err) => {
|
||||||
|
return Err(Exceptions::ReedSolomonException(
|
||||||
|
"IllegalArgumentException".to_owned(),
|
||||||
|
))
|
||||||
|
}
|
||||||
}) {
|
}) {
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(err) => return Err(Exceptions::ReedSolomonException("IllegalArgumentException".to_owned())),
|
Err(err) => {
|
||||||
|
return Err(Exceptions::ReedSolomonException(
|
||||||
|
"IllegalArgumentException".to_owned(),
|
||||||
|
))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
t = match (match q.multiply(&tLast) {
|
t = match (match q.multiply(&tLast) {
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(err) => return Err(Exceptions::ReedSolomonException("IllegalArgumentException".to_owned())),
|
Err(err) => {
|
||||||
|
return Err(Exceptions::ReedSolomonException(
|
||||||
|
"IllegalArgumentException".to_owned(),
|
||||||
|
))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.addOrSubtract(&tLastLast)
|
.addOrSubtract(&tLastLast)
|
||||||
{
|
{
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(err) => return Err(Exceptions::ReedSolomonException("IllegalArgumentException".to_owned())),
|
Err(err) => {
|
||||||
|
return Err(Exceptions::ReedSolomonException(
|
||||||
|
"IllegalArgumentException".to_owned(),
|
||||||
|
))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if r.getDegree() >= rLast.getDegree() {
|
if r.getDegree() >= rLast.getDegree() {
|
||||||
@@ -777,22 +825,25 @@ impl ReedSolomonDecoder {
|
|||||||
|
|
||||||
let sigmaTildeAtZero = t.getCoefficient(0);
|
let sigmaTildeAtZero = t.getCoefficient(0);
|
||||||
if sigmaTildeAtZero == 0 {
|
if sigmaTildeAtZero == 0 {
|
||||||
return Err(Exceptions::ReedSolomonException("sigmaTilde(0) was zero".to_owned()));
|
return Err(Exceptions::ReedSolomonException(
|
||||||
|
"sigmaTilde(0) was zero".to_owned(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let inverse = match self.field.inverse(sigmaTildeAtZero) {
|
let inverse = match self.field.inverse(sigmaTildeAtZero) {
|
||||||
Ok(res) => res,
|
Ok(res) => res,
|
||||||
Err(err) => return Err(Exceptions::ReedSolomonException("ArithmetricException".to_owned())),
|
Err(err) => {
|
||||||
|
return Err(Exceptions::ReedSolomonException(
|
||||||
|
"ArithmetricException".to_owned(),
|
||||||
|
))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let sigma = t.multiply_with_scalar(inverse);
|
let sigma = t.multiply_with_scalar(inverse);
|
||||||
let omega = r.multiply_with_scalar(inverse);
|
let omega = r.multiply_with_scalar(inverse);
|
||||||
return Ok(vec![sigma, omega]);
|
return Ok(vec![sigma, omega]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn findErrorLocations(
|
fn findErrorLocations(&self, errorLocator: &GenericGFPoly) -> Result<Vec<usize>, Exceptions> {
|
||||||
&self,
|
|
||||||
errorLocator: &GenericGFPoly,
|
|
||||||
) -> Result<Vec<usize>, Exceptions> {
|
|
||||||
// This is a direct application of Chien's search
|
// This is a direct application of Chien's search
|
||||||
let numErrors = errorLocator.getDegree();
|
let numErrors = errorLocator.getDegree();
|
||||||
if numErrors == 1 {
|
if numErrors == 1 {
|
||||||
@@ -800,17 +851,21 @@ impl ReedSolomonDecoder {
|
|||||||
return Ok(vec![errorLocator.getCoefficient(1).try_into().unwrap()]);
|
return Ok(vec![errorLocator.getCoefficient(1).try_into().unwrap()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result: Vec<usize> = Vec::with_capacity(numErrors);
|
let mut result: Vec<usize> = vec![0; numErrors];
|
||||||
let mut e = 0;
|
let mut e = 0;
|
||||||
for i in 1..self.field.getSize() {
|
for i in 1..self.field.getSize() {
|
||||||
//for (int i = 1; i < field.getSize() && e < numErrors; i++) {
|
//for (int i = 1; i < field.getSize() && e < numErrors; i++) {
|
||||||
if e < numErrors {
|
if e >= numErrors {
|
||||||
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.try_into().unwrap()) {
|
||||||
Ok(res) => res.try_into().unwrap(),
|
Ok(res) => res.try_into().unwrap(),
|
||||||
Err(err) => return Err(Exceptions::ReedSolomonException("ArithmetricException".to_owned())),
|
Err(err) => {
|
||||||
|
return Err(Exceptions::ReedSolomonException(
|
||||||
|
"ArithmetricException".to_owned(),
|
||||||
|
))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
e += 1;
|
e += 1;
|
||||||
}
|
}
|
||||||
@@ -830,7 +885,7 @@ impl ReedSolomonDecoder {
|
|||||||
) -> Vec<i32> {
|
) -> Vec<i32> {
|
||||||
// This is directly applying Forney's Formula
|
// This is directly applying Forney's Formula
|
||||||
let s = errorLocations.len();
|
let s = errorLocations.len();
|
||||||
let mut result = Vec::with_capacity(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
|
||||||
@@ -939,33 +994,34 @@ impl ReedSolomonEncoder {
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encode(
|
pub fn encode(&mut self, to_encode: &mut Vec<i32>, ec_bytes: usize) -> Result<(), Exceptions> {
|
||||||
&mut self,
|
if ec_bytes == 0 {
|
||||||
toEncode: &mut Vec<i32>,
|
return Err(Exceptions::IllegalArgumentException(
|
||||||
ecBytes: usize,
|
"No error correction bytes".to_owned(),
|
||||||
) -> Result<(), Exceptions> {
|
));
|
||||||
if ecBytes == 0 {
|
|
||||||
return Err(Exceptions::IllegalArgumentException("No error correction bytes".to_owned()));
|
|
||||||
}
|
}
|
||||||
let dataBytes = toEncode.len() - ecBytes;
|
let data_bytes = to_encode.len() - ec_bytes;
|
||||||
if dataBytes <= 0 {
|
if data_bytes <= 0 {
|
||||||
return Err(Exceptions::IllegalArgumentException("No data bytes provided".to_owned()));
|
return Err(Exceptions::IllegalArgumentException(
|
||||||
|
"No data bytes provided".to_owned(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
let fld = self.field.clone();
|
let fld = self.field.clone();
|
||||||
let generator = self.buildGenerator(ecBytes);
|
let generator = self.buildGenerator(ec_bytes);
|
||||||
let mut infoCoefficients: Vec<i32> = vec![0;dataBytes];//Vec::with_capacity(dataBytes);
|
let mut info_coefficients: Vec<i32> = vec![0; data_bytes];
|
||||||
infoCoefficients[0..dataBytes].clone_from_slice(&toEncode[0..dataBytes]);
|
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, &infoCoefficients)?;
|
let mut info = GenericGFPoly::new(fld, &info_coefficients)?;
|
||||||
info = info.multiplyByMonomial(ecBytes.try_into().unwrap(), 1)?;
|
info = info.multiply_by_monomial(ec_bytes.try_into().unwrap(), 1)?;
|
||||||
let remainder = &info.divide(&generator)?[1];
|
let remainder = &info.divide(&generator)?.1;
|
||||||
let coefficients = remainder.getCoefficients();
|
let coefficients = remainder.getCoefficients();
|
||||||
let numZeroCoefficients = ecBytes - coefficients.len();
|
let num_zero_coefficients = ec_bytes - coefficients.len();
|
||||||
for i in 0..numZeroCoefficients {
|
for i in 0..num_zero_coefficients {
|
||||||
//for (int i = 0; i < numZeroCoefficients; i++) {
|
//for (int i = 0; i < numZeroCoefficients; i++) {
|
||||||
toEncode[dataBytes + i] = 0;
|
to_encode[data_bytes + i] = 0;
|
||||||
}
|
}
|
||||||
toEncode[dataBytes + numZeroCoefficients..coefficients.len()]
|
to_encode[data_bytes + num_zero_coefficients
|
||||||
|
..(coefficients.len() + data_bytes + num_zero_coefficients)]
|
||||||
.clone_from_slice(&coefficients[0..coefficients.len()]);
|
.clone_from_slice(&coefficients[0..coefficients.len()]);
|
||||||
//System.arraycopy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.length);
|
//System.arraycopy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.length);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user