Skip to content

Commit

Permalink
Add support for CRC algorithms which have a non-power of 2 width
Browse files Browse the repository at this point in the history
  • Loading branch information
bartelsielski authored and akhilles committed Nov 4, 2021
1 parent f1294c9 commit 384fb68
Show file tree
Hide file tree
Showing 11 changed files with 266 additions and 82 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Expand Up @@ -15,4 +15,4 @@ categories = ["algorithms", "no-std"]
edition = "2018"

[dependencies]
crc-catalog = "1.1.1"
crc-catalog = "2.0.1"
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -27,6 +27,7 @@ assert_eq!(CASTAGNOLI.checksum(b"123456789"), 0xe3069283);

// use custom algorithm
const CUSTOM_ALG: Algorithm<u16> = Algorithm {
width: 16,
poly: 0x8005,
init: 0xffff,
refin: false,
Expand Down
20 changes: 19 additions & 1 deletion benches/bench.rs
Expand Up @@ -5,6 +5,7 @@ use criterion::{Benchmark, Criterion, Throughput};
pub const BLUETOOTH: Crc<u8> = Crc::<u8>::new(&CRC_8_BLUETOOTH);
pub const X25: Crc<u16> = Crc::<u16>::new(&CRC_16_IBM_SDLC);
pub const CASTAGNOLI: Crc<u32> = Crc::<u32>::new(&CRC_32_ISCSI);
pub const GSM_40: Crc<u64> = Crc::<u64>::new(&CRC_40_GSM);
pub const ECMA: Crc<u64> = Crc::<u64>::new(&CRC_64_ECMA_182);

fn crc8(c: &mut Criterion) {
Expand Down Expand Up @@ -37,6 +38,16 @@ fn crc32(c: &mut Criterion) {
);
}

fn crc40(c: &mut Criterion) {
let mut digest = GSM_40.digest();
let bytes = vec![0u8; 1_000_000];
c.bench(
"crc40",
Benchmark::new("crc40", move |b| b.iter(|| digest.update(&bytes)))
.throughput(Throughput::Bytes(1_000_000)),
);
}

fn crc64(c: &mut Criterion) {
let mut digest = ECMA.digest();
let bytes = vec![0u8; 1_000_000];
Expand All @@ -50,5 +61,12 @@ fn crc64(c: &mut Criterion) {
criterion_group!(crc8_benches, crc8);
criterion_group!(crc16_benches, crc16);
criterion_group!(crc32_benches, crc32);
criterion_group!(crc40_benches, crc40);
criterion_group!(crc64_benches, crc64);
criterion_main!(crc8_benches, crc16_benches, crc32_benches, crc64_benches);
criterion_main!(
crc8_benches,
crc16_benches,
crc32_benches,
crc40_benches,
crc64_benches,
);
15 changes: 10 additions & 5 deletions src/crc16.rs
Expand Up @@ -3,7 +3,7 @@ use crate::table::crc16_table;

impl Crc<u16> {
pub const fn new(algorithm: &'static Algorithm<u16>) -> Self {
let table = crc16_table(algorithm.poly, algorithm.refin);
let table = crc16_table(algorithm.width, algorithm.poly, algorithm.refin);
Self { algorithm, table }
}

Expand All @@ -15,9 +15,9 @@ impl Crc<u16> {

const fn init(&self) -> u16 {
if self.algorithm.refin {
self.algorithm.init.reverse_bits()
self.algorithm.init.reverse_bits() >> (u16::BITS as u8 - self.algorithm.width)
} else {
self.algorithm.init
self.algorithm.init << (u16::BITS as u8 - self.algorithm.width)
}
}

Expand All @@ -29,12 +29,14 @@ impl Crc<u16> {
let mut i = 0;
if self.algorithm.refin {
while i < bytes.len() {
crc = self.table_entry(crc ^ bytes[i] as u16) ^ (crc >> 8);
let table_index = crc ^ bytes[i] as u16;
crc = self.table_entry(table_index) ^ (crc >> 8);
i += 1;
}
} else {
while i < bytes.len() {
crc = self.table_entry(bytes[i] as u16 ^ (crc >> 8)) ^ (crc << 8);
let table_index = (crc >> (u16::BITS - 8)) ^ bytes[i] as u16;
crc = self.table_entry(table_index) ^ (crc << 8);
i += 1;
}
}
Expand All @@ -45,6 +47,9 @@ impl Crc<u16> {
if self.algorithm.refin ^ self.algorithm.refout {
crc = crc.reverse_bits();
}
if !self.algorithm.refout {
crc >>= u16::BITS as u8 - self.algorithm.width;
}
crc ^ self.algorithm.xorout
}

Expand Down
15 changes: 10 additions & 5 deletions src/crc32.rs
Expand Up @@ -3,7 +3,7 @@ use crate::table::crc32_table;

impl Crc<u32> {
pub const fn new(algorithm: &'static Algorithm<u32>) -> Self {
let table = crc32_table(algorithm.poly, algorithm.refin);
let table = crc32_table(algorithm.width, algorithm.poly, algorithm.refin);
Self { algorithm, table }
}

Expand All @@ -15,9 +15,9 @@ impl Crc<u32> {

const fn init(&self) -> u32 {
if self.algorithm.refin {
self.algorithm.init.reverse_bits()
self.algorithm.init.reverse_bits() >> (u32::BITS as u8 - self.algorithm.width)
} else {
self.algorithm.init
self.algorithm.init << (u32::BITS as u8 - self.algorithm.width)
}
}

Expand All @@ -29,12 +29,14 @@ impl Crc<u32> {
let mut i = 0;
if self.algorithm.refin {
while i < bytes.len() {
crc = self.table_entry(crc ^ bytes[i] as u32) ^ (crc >> 8);
let table_index = crc ^ bytes[i] as u32;
crc = self.table_entry(table_index) ^ (crc >> 8);
i += 1;
}
} else {
while i < bytes.len() {
crc = self.table_entry(bytes[i] as u32 ^ (crc >> 24)) ^ (crc << 8);
let table_index = (crc >> (u32::BITS - 8)) ^ bytes[i] as u32;
crc = self.table_entry(table_index) ^ (crc << 8);
i += 1;
}
}
Expand All @@ -45,6 +47,9 @@ impl Crc<u32> {
if self.algorithm.refin ^ self.algorithm.refout {
crc = crc.reverse_bits();
}
if !self.algorithm.refout {
crc >>= u32::BITS as u8 - self.algorithm.width;
}
crc ^ self.algorithm.xorout
}

Expand Down
15 changes: 10 additions & 5 deletions src/crc64.rs
Expand Up @@ -3,7 +3,7 @@ use crate::table::crc64_table;

impl Crc<u64> {
pub const fn new(algorithm: &'static Algorithm<u64>) -> Self {
let table = crc64_table(algorithm.poly, algorithm.refin);
let table = crc64_table(algorithm.width, algorithm.poly, algorithm.refin);
Self { algorithm, table }
}

Expand All @@ -15,9 +15,9 @@ impl Crc<u64> {

const fn init(&self) -> u64 {
if self.algorithm.refin {
self.algorithm.init.reverse_bits()
self.algorithm.init.reverse_bits() >> (u64::BITS as u8 - self.algorithm.width)
} else {
self.algorithm.init
self.algorithm.init << (u64::BITS as u8 - self.algorithm.width)
}
}

Expand All @@ -29,12 +29,14 @@ impl Crc<u64> {
let mut i = 0;
if self.algorithm.refin {
while i < bytes.len() {
crc = self.table_entry(crc ^ bytes[i] as u64) ^ (crc >> 8);
let table_index = crc ^ bytes[i] as u64;
crc = self.table_entry(table_index) ^ (crc >> 8);
i += 1;
}
} else {
while i < bytes.len() {
crc = self.table_entry(bytes[i] as u64 ^ (crc >> 56)) ^ (crc << 8);
let table_index = (crc >> (u64::BITS - 8)) ^ bytes[i] as u64;
crc = self.table_entry(table_index) ^ (crc << 8);
i += 1;
}
}
Expand All @@ -45,6 +47,9 @@ impl Crc<u64> {
if self.algorithm.refin ^ self.algorithm.refout {
crc = crc.reverse_bits();
}
if !self.algorithm.refout {
crc >>= u64::BITS as u8 - self.algorithm.width;
}
crc ^ self.algorithm.xorout
}

Expand Down
9 changes: 6 additions & 3 deletions src/crc8.rs
Expand Up @@ -3,7 +3,7 @@ use crate::table::crc8_table;

impl Crc<u8> {
pub const fn new(algorithm: &'static Algorithm<u8>) -> Self {
let table = crc8_table(algorithm.poly, algorithm.refin);
let table = crc8_table(algorithm.width, algorithm.poly, algorithm.refin);
Self { algorithm, table }
}

Expand All @@ -15,9 +15,9 @@ impl Crc<u8> {

const fn init(&self) -> u8 {
if self.algorithm.refin {
self.algorithm.init.reverse_bits()
self.algorithm.init.reverse_bits() >> (u8::BITS as u8 - self.algorithm.width)
} else {
self.algorithm.init
self.algorithm.init << (u8::BITS as u8 - self.algorithm.width)
}
}

Expand All @@ -40,6 +40,9 @@ impl Crc<u8> {
if self.algorithm.refin ^ self.algorithm.refout {
crc = crc.reverse_bits();
}
if !self.algorithm.refout {
crc >>= u8::BITS as u8 - self.algorithm.width;
}
crc ^ self.algorithm.xorout
}

Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Expand Up @@ -14,6 +14,7 @@
//!
//! // use custom algorithm
//! const CUSTOM_ALG: Algorithm<u16> = Algorithm {
//! width: 16,
//! poly: 0x8005,
//! init: 0xffff,
//! refin: false,
Expand Down
45 changes: 38 additions & 7 deletions src/table.rs
@@ -1,6 +1,13 @@
use crate::util::*;

pub(crate) const fn crc8_table(poly: u8, reflect: bool) -> [u8; 256] {
pub(crate) const fn crc8_table(width: u8, poly: u8, reflect: bool) -> [u8; 256] {
let poly = if reflect {
let poly = poly.reverse_bits();
poly >> (u8::BITS as u8 - width)
} else {
poly << (u8::BITS as u8 - width)
};

let mut table = [0u8; 256];
let mut i = 0;
while i < table.len() {
Expand All @@ -9,29 +16,53 @@ pub(crate) const fn crc8_table(poly: u8, reflect: bool) -> [u8; 256] {
}
table
}
pub(crate) const fn crc16_table(poly: u16, reflect: bool) -> [u16; 256] {

pub(crate) const fn crc16_table(width: u8, poly: u16, reflect: bool) -> [u16; 256] {
let poly = if reflect {
let poly = poly.reverse_bits();
poly >> (u16::BITS as u8 - width)
} else {
poly << (u16::BITS as u8 - width)
};

let mut table = [0u16; 256];
let mut i = 0;
while i < table.len() {
table[i] = crc16(poly, reflect, i as u8);
table[i] = crc16(poly, reflect, i as u16);
i += 1;
}
table
}
pub(crate) const fn crc32_table(poly: u32, reflect: bool) -> [u32; 256] {

pub(crate) const fn crc32_table(width: u8, poly: u32, reflect: bool) -> [u32; 256] {
let poly = if reflect {
let poly = poly.reverse_bits();
poly >> (u32::BITS as u8 - width)
} else {
poly << (u32::BITS as u8 - width)
};

let mut table = [0u32; 256];
let mut i = 0;
while i < table.len() {
table[i] = crc32(poly, reflect, i as u8);
table[i] = crc32(poly, reflect, i as u32);
i += 1;
}
table
}
pub(crate) const fn crc64_table(poly: u64, reflect: bool) -> [u64; 256] {

pub(crate) const fn crc64_table(width: u8, poly: u64, reflect: bool) -> [u64; 256] {
let poly = if reflect {
let poly = poly.reverse_bits();
poly >> (u64::BITS as u8 - width)
} else {
poly << (u64::BITS as u8 - width)
};

let mut table = [0u64; 256];
let mut i = 0;
while i < table.len() {
table[i] = crc64(poly, reflect, i as u8);
table[i] = crc64(poly, reflect, i as u64);
i += 1;
}
table
Expand Down

0 comments on commit 384fb68

Please sign in to comment.