diff --git a/src/crc128/bytewise.rs b/src/crc128/bytewise.rs index 500d7ea..9a963ac 100644 --- a/src/crc128/bytewise.rs +++ b/src/crc128/bytewise.rs @@ -15,7 +15,7 @@ impl Crc> { finalize(self.algorithm, crc) } - const fn update(&self, crc: u128, bytes: &[u8]) -> u128 { + pub(crate) const fn update(&self, crc: u128, bytes: &[u8]) -> u128 { update_bytewise(crc, self.algorithm.refin, &self.table, bytes) } diff --git a/src/crc128/default.rs b/src/crc128/default.rs index d623ac4..1289b2c 100644 --- a/src/crc128/default.rs +++ b/src/crc128/default.rs @@ -1,37 +1,5 @@ use crate::crc128::{finalize, init}; -use crate::{Algorithm, Crc, Digest, Implementation}; - -#[cfg(feature = "no-table-mem-limit")] -impl Implementation for u128 { - type Width = u128; - type Table = (); -} - -#[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] -impl Implementation for u128 { - type Width = u128; - type Table = [u128; 256]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" -))] -impl Implementation for u128 { - type Width = u128; - type Table = [[u128; 256]; 16]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") -))] -impl Implementation for u128 { - type Width = u128; - type Table = [u128; 256]; -} +use crate::{Algorithm, Crc, Digest}; impl Crc { pub const fn new(algorithm: &'static Algorithm) -> Self { diff --git a/src/crc16.rs b/src/crc16.rs index 427906c..c22fbf0 100644 --- a/src/crc16.rs +++ b/src/crc16.rs @@ -4,6 +4,11 @@ use crc_catalog::Algorithm; mod bytewise; mod default; mod nolookup; +#[cfg(all( + target_feature = "sse2", + target_feature = "sse4.1", + target_feature = "pclmulqdq" +))] mod simd; mod slice16; diff --git a/src/crc16/bytewise.rs b/src/crc16/bytewise.rs index 1f042dd..7ec1856 100644 --- a/src/crc16/bytewise.rs +++ b/src/crc16/bytewise.rs @@ -14,7 +14,7 @@ impl Crc> { finalize(self.algorithm, crc) } - const fn update(&self, crc: u16, bytes: &[u8]) -> u16 { + pub(super) const fn update(&self, crc: u16, bytes: &[u8]) -> u16 { update_bytewise(crc, self.algorithm.refin, &self.table, bytes) } diff --git a/src/crc16/default.rs b/src/crc16/default.rs index 55b72c9..ce0d241 100644 --- a/src/crc16/default.rs +++ b/src/crc16/default.rs @@ -1,61 +1,29 @@ use crate::crc16::{finalize, init}; -use crate::{Algorithm, Crc, Digest, Implementation}; - -#[cfg(feature = "no-table-mem-limit")] -impl Implementation for u16 { - type Width = u16; - type Table = (); -} - -#[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] -impl Implementation for u16 { - type Width = u16; - type Table = [u16; 256]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" -))] -impl Implementation for u16 { - type Width = u16; - type Table = [[u16; 256]; 16]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") -))] -impl Implementation for u16 { - type Width = u16; - type Table = [u16; 256]; -} +use crate::{Algorithm, Crc, Digest}; impl Crc { pub const fn new(algorithm: &'static Algorithm) -> Self { + #[cfg(feature = "no-table-mem-limit")] + let table = Crc::>::new(algorithm); + #[cfg(all( not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" + any( + all( + not(feature = "bytewise-mem-limit"), + not(feature = "slice16-mem-limit") + ), + feature = "bytewise-mem-limit" + ) ))] - let table = - crate::table::crc16_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - let table = crate::table::crc16_table(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(feature = "no-table-mem-limit")] - #[allow(clippy::let_unit_value)] - let table = (); + let table = Crc::>::new(algorithm); #[cfg(all( not(feature = "no-table-mem-limit"), not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") + feature = "slice16-mem-limit" ))] - let table = crate::table::crc16_table(algorithm.width, algorithm.poly, algorithm.refin); + let table = Crc::>::new(algorithm); Self { algorithm, table } } @@ -67,33 +35,7 @@ impl Crc { } const fn update(&self, crc: u16, bytes: &[u8]) -> u16 { - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - super::update_slice16(crc, self.algorithm.refin, &self.table, bytes) - } - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - { - super::update_bytewise(crc, self.algorithm.refin, &self.table, bytes) - } - - #[cfg(feature = "no-table-mem-limit")] - { - super::update_nolookup(crc, self.algorithm, bytes) - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - super::update_bytewise(crc, self.algorithm.refin, &self.table, bytes) - } + self.table.update(crc, bytes) } pub const fn digest(&self) -> Digest { diff --git a/src/crc16/nolookup.rs b/src/crc16/nolookup.rs index eedf5a2..4890a8d 100644 --- a/src/crc16/nolookup.rs +++ b/src/crc16/nolookup.rs @@ -15,7 +15,7 @@ impl Crc> { finalize(self.algorithm, crc) } - const fn update(&self, crc: u16, bytes: &[u8]) -> u16 { + pub(super) const fn update(&self, crc: u16, bytes: &[u8]) -> u16 { update_nolookup(crc, self.algorithm, bytes) } diff --git a/src/crc16/simd.rs b/src/crc16/simd.rs index 1387714..2fa64e8 100644 --- a/src/crc16/simd.rs +++ b/src/crc16/simd.rs @@ -1,5 +1,4 @@ -use crate::crc32::update_simd; -use crate::simd::{SimdValue, SimdValueOps}; +use crate::simd::{crc32_update_refin, SimdValue}; use crate::table::{crc16_table_slice_16, crc32_simd_coefficients}; use crate::{Algorithm, Crc, Digest, Simd}; @@ -28,16 +27,19 @@ impl Crc> { finalize(self.algorithm, crc) } - fn update(&self, mut crc: u16, bytes: &[u8]) -> u16 { - if !SimdValue::is_supported() || !self.algorithm.refin { + pub(super) fn update(&self, mut crc: u16, bytes: &[u8]) -> u16 { + if !self.algorithm.refin { return update_slice16(crc, self.algorithm.refin, &self.table.0, bytes); } + // SAFETY: Both represent numbers let (bytes_before, chunks, bytes_after) = unsafe { bytes.align_to::<[SimdValue; 4]>() }; crc = update_slice16(crc, self.algorithm.refin, &self.table.0, bytes_before); if let Some(first_chunk) = chunks.first() { // SAFETY: All required features are supported, by checking SimdValue::is_supported. - crc = unsafe { update_simd(crc as u32, &self.table.1, first_chunk, chunks) } as u16; + crc = + unsafe { crc32_update_refin(crc as u32, &self.table.1, first_chunk, &chunks[1..]) } + as u16; } update_slice16(crc, self.algorithm.refin, &self.table.0, bytes_after) } diff --git a/src/crc32.rs b/src/crc32.rs index fd4ec28..8f16768 100644 --- a/src/crc32.rs +++ b/src/crc32.rs @@ -1,10 +1,14 @@ -use crate::simd::{SimdValue, SimdValueOps}; use crate::util::crc32; use crc_catalog::Algorithm; mod bytewise; mod default; mod nolookup; +#[cfg(all( + target_feature = "sse2", + target_feature = "sse4.1", + target_feature = "pclmulqdq" +))] mod simd; mod slice16; @@ -152,42 +156,6 @@ const fn update_slice16( crc } -#[target_feature(enable = "sse2", enable = "sse4.1", enable = "pclmulqdq")] -pub(crate) unsafe fn update_simd( - crc: u32, - coefficients: &[SimdValue; 4], - first_chunk: &[SimdValue; 4], - chunks: &[[SimdValue; 4]], -) -> u32 { - let mut x4 = *first_chunk; - - // Apply initial crc value - x4[0] = x4[0].xor(crc as u64); - - // Iteratively Fold by 4: - let k1_k2 = coefficients[0]; - for chunk in chunks { - for (x, value) in x4.iter_mut().zip(chunk.iter()) { - *x = x.fold_16(k1_k2, *value) - } - } - - // Iteratively Fold by 1: - let k3_k4 = coefficients[1]; - let mut x = x4[0].fold_16(k3_k4, x4[1]); - x = x.fold_16(k3_k4, x4[2]); - x = x.fold_16(k3_k4, x4[3]); - - // Final Reduction of 128-bits - let k5_k6 = coefficients[2]; - x = x.fold_8(k3_k4); - x = x.fold_4(k5_k6); - - // Barret Reduction - let px_u = coefficients[3]; - x.barret_reduction_32(px_u) -} - #[cfg(test)] mod test { use crate::{Bytewise, Crc, Implementation, NoTable, Simd, Slice16}; diff --git a/src/crc32/bytewise.rs b/src/crc32/bytewise.rs index 88c7976..091fec0 100644 --- a/src/crc32/bytewise.rs +++ b/src/crc32/bytewise.rs @@ -15,7 +15,7 @@ impl Crc> { finalize(self.algorithm, crc) } - const fn update(&self, crc: u32, bytes: &[u8]) -> u32 { + pub(super) const fn update(&self, crc: u32, bytes: &[u8]) -> u32 { update_bytewise(crc, self.algorithm.refin, &self.table, bytes) } diff --git a/src/crc32/default.rs b/src/crc32/default.rs index 0aaedd3..7ded2dd 100644 --- a/src/crc32/default.rs +++ b/src/crc32/default.rs @@ -1,61 +1,29 @@ use crate::crc32::{finalize, init}; -use crate::{Algorithm, Crc, Digest, Implementation}; - -#[cfg(feature = "no-table-mem-limit")] -impl Implementation for u32 { - type Width = u32; - type Table = (); -} - -#[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] -impl Implementation for u32 { - type Width = u32; - type Table = [u32; 256]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" -))] -impl Implementation for u32 { - type Width = u32; - type Table = [[u32; 256]; 16]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") -))] -impl Implementation for u32 { - type Width = u32; - type Table = [u32; 256]; -} +use crate::{Algorithm, Crc, Digest}; impl Crc { pub const fn new(algorithm: &'static Algorithm) -> Self { + #[cfg(feature = "no-table-mem-limit")] + let table = Crc::>::new(algorithm); + #[cfg(all( not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" + any( + all( + not(feature = "bytewise-mem-limit"), + not(feature = "slice16-mem-limit") + ), + feature = "bytewise-mem-limit" + ) ))] - let table = - crate::table::crc32_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - let table = crate::table::crc32_table(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(feature = "no-table-mem-limit")] - #[allow(clippy::let_unit_value)] - let table = (); + let table = Crc::>::new(algorithm); #[cfg(all( not(feature = "no-table-mem-limit"), not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") + feature = "slice16-mem-limit" ))] - let table = crate::table::crc32_table(algorithm.width, algorithm.poly, algorithm.refin); + let table = Crc::>::new(algorithm); Self { algorithm, table } } @@ -67,33 +35,7 @@ impl Crc { } const fn update(&self, crc: u32, bytes: &[u8]) -> u32 { - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - super::update_slice16(crc, self.algorithm.refin, &self.table, bytes) - } - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - { - super::update_bytewise(crc, self.algorithm.refin, &self.table, bytes) - } - - #[cfg(feature = "no-table-mem-limit")] - { - super::update_nolookup(crc, self.algorithm, bytes) - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - super::update_bytewise(crc, self.algorithm.refin, &self.table, bytes) - } + self.table.update(crc, bytes) } pub const fn digest(&self) -> Digest { diff --git a/src/crc32/nolookup.rs b/src/crc32/nolookup.rs index de40987..88fac13 100644 --- a/src/crc32/nolookup.rs +++ b/src/crc32/nolookup.rs @@ -16,7 +16,7 @@ impl Crc> { finalize(self.algorithm, crc) } - const fn update(&self, crc: u32, bytes: &[u8]) -> u32 { + pub(super) const fn update(&self, crc: u32, bytes: &[u8]) -> u32 { update_nolookup(crc, self.algorithm, bytes) } diff --git a/src/crc32/simd.rs b/src/crc32/simd.rs index 21f18b1..c269ba6 100644 --- a/src/crc32/simd.rs +++ b/src/crc32/simd.rs @@ -1,8 +1,8 @@ -use crate::simd::{SimdValue, SimdValueOps}; +use crate::simd::{crc32_update_refin, SimdValue}; use crate::table::{crc32_simd_coefficients, crc32_table_slice_16}; use crate::{Algorithm, Crc, Digest, Simd}; -use super::{finalize, init, update_simd, update_slice16}; +use super::{finalize, init, update_slice16}; impl Crc> { pub const fn new(algorithm: &'static Algorithm) -> Self { @@ -24,8 +24,8 @@ impl Crc> { finalize(self.algorithm, crc) } - fn update(&self, mut crc: u32, bytes: &[u8]) -> u32 { - if !SimdValue::is_supported() || !self.algorithm.refin { + pub(super) fn update(&self, mut crc: u32, bytes: &[u8]) -> u32 { + if !self.algorithm.refin { return update_slice16(crc, self.algorithm.refin, &self.table.0, bytes); } @@ -34,7 +34,7 @@ impl Crc> { crc = update_slice16(crc, self.algorithm.refin, &self.table.0, bytes_before); if let Some(first_chunk) = chunks.first() { // SAFETY: All required features are supported, by checking SimdValue::is_supported. - crc = unsafe { update_simd(crc, &self.table.1, first_chunk, &chunks[1..]) }; + crc = unsafe { crc32_update_refin(crc, &self.table.1, first_chunk, &chunks[1..]) }; } update_slice16(crc, self.algorithm.refin, &self.table.0, bytes_after) } diff --git a/src/crc64.rs b/src/crc64.rs index 186531e..9abafd2 100644 --- a/src/crc64.rs +++ b/src/crc64.rs @@ -154,7 +154,7 @@ const fn update_slice16( #[cfg(test)] mod test { - use crate::{Bytewise, Crc, Implementation, NoTable, Simd, Slice16}; + use crate::{Bytewise, Crc, Implementation, NoTable, Slice16}; use crc_catalog::{Algorithm, CRC_64_ECMA_182}; #[test] diff --git a/src/crc64/default.rs b/src/crc64/default.rs index bf41dc8..0d0e152 100644 --- a/src/crc64/default.rs +++ b/src/crc64/default.rs @@ -1,37 +1,5 @@ use crate::crc64::{finalize, init}; -use crate::{Algorithm, Crc, Digest, Implementation}; - -#[cfg(feature = "no-table-mem-limit")] -impl Implementation for u64 { - type Width = u64; - type Table = (); -} - -#[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] -impl Implementation for u64 { - type Width = u64; - type Table = [u64; 256]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" -))] -impl Implementation for u64 { - type Width = u64; - type Table = [[u64; 256]; 16]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") -))] -impl Implementation for u64 { - type Width = u64; - type Table = [u64; 256]; -} +use crate::{Algorithm, Crc, Digest}; impl Crc { pub const fn new(algorithm: &'static Algorithm) -> Self { diff --git a/src/crc8.rs b/src/crc8.rs index 73aaea8..17f4d89 100644 --- a/src/crc8.rs +++ b/src/crc8.rs @@ -4,6 +4,11 @@ use crc_catalog::Algorithm; mod bytewise; mod default; mod nolookup; +#[cfg(all( + target_feature = "sse2", + target_feature = "sse4.1", + target_feature = "pclmulqdq" +))] mod simd; mod slice16; diff --git a/src/crc8/bytewise.rs b/src/crc8/bytewise.rs index 1cae39e..e6a35a4 100644 --- a/src/crc8/bytewise.rs +++ b/src/crc8/bytewise.rs @@ -14,7 +14,7 @@ impl Crc> { finalize(self.algorithm, crc) } - const fn update(&self, crc: u8, bytes: &[u8]) -> u8 { + pub(super) const fn update(&self, crc: u8, bytes: &[u8]) -> u8 { update_bytewise(crc, &self.table, bytes) } diff --git a/src/crc8/default.rs b/src/crc8/default.rs index 9923b3a..2feef70 100644 --- a/src/crc8/default.rs +++ b/src/crc8/default.rs @@ -1,61 +1,29 @@ use crate::crc8::{finalize, init}; -use crate::{Algorithm, Crc, Digest, Implementation}; - -#[cfg(feature = "no-table-mem-limit")] -impl Implementation for u8 { - type Width = u8; - type Table = (); -} - -#[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] -impl Implementation for u8 { - type Width = u8; - type Table = [u8; 256]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" -))] -impl Implementation for u8 { - type Width = u8; - type Table = [[u8; 256]; 16]; -} - -#[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") -))] -impl Implementation for u8 { - type Width = u8; - type Table = [u8; 256]; -} +use crate::{Algorithm, Crc, Digest}; impl Crc { pub const fn new(algorithm: &'static Algorithm) -> Self { + #[cfg(feature = "no-table-mem-limit")] + let table = Crc::>::new(algorithm); + #[cfg(all( not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" + any( + all( + not(feature = "bytewise-mem-limit"), + not(feature = "slice16-mem-limit") + ), + feature = "bytewise-mem-limit" + ) ))] - let table = - crate::table::crc8_table_slice_16(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - let table = crate::table::crc8_table(algorithm.width, algorithm.poly, algorithm.refin); - - #[cfg(feature = "no-table-mem-limit")] - #[allow(clippy::let_unit_value)] - let table = (); + let table = Crc::>::new(algorithm); #[cfg(all( not(feature = "no-table-mem-limit"), not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") + feature = "slice16-mem-limit" ))] - let table = crate::table::crc8_table(algorithm.width, algorithm.poly, algorithm.refin); + let table = Crc::>::new(algorithm); Self { algorithm, table } } @@ -67,33 +35,7 @@ impl Crc { } const fn update(&self, crc: u8, bytes: &[u8]) -> u8 { - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - feature = "slice16-mem-limit" - ))] - { - super::update_slice16(crc, &self.table, bytes) - } - - #[cfg(all(not(feature = "no-table-mem-limit"), feature = "bytewise-mem-limit"))] - { - super::update_bytewise(crc, &self.table, bytes) - } - - #[cfg(feature = "no-table-mem-limit")] - { - super::update_nolookup(crc, self.algorithm, bytes) - } - - #[cfg(all( - not(feature = "no-table-mem-limit"), - not(feature = "bytewise-mem-limit"), - not(feature = "slice16-mem-limit") - ))] - { - super::update_bytewise(crc, &self.table, bytes) - } + self.table.update(crc, bytes) } pub const fn digest(&self) -> Digest { diff --git a/src/crc8/nolookup.rs b/src/crc8/nolookup.rs index 4b19340..8178d77 100644 --- a/src/crc8/nolookup.rs +++ b/src/crc8/nolookup.rs @@ -15,7 +15,7 @@ impl Crc> { finalize(self.algorithm, crc) } - const fn update(&self, crc: u8, bytes: &[u8]) -> u8 { + pub(super) const fn update(&self, crc: u8, bytes: &[u8]) -> u8 { update_nolookup(crc, self.algorithm, bytes) } diff --git a/src/crc8/simd.rs b/src/crc8/simd.rs index cda6dc0..26b5197 100644 --- a/src/crc8/simd.rs +++ b/src/crc8/simd.rs @@ -1,5 +1,4 @@ -use crate::crc32::update_simd; -use crate::simd::{SimdValue, SimdValueOps}; +use crate::simd::{crc32_update_refin, SimdValue}; use crate::table::{crc32_simd_coefficients, crc8_table_slice_16}; use crate::{Algorithm, Crc, Digest, Simd}; @@ -28,16 +27,19 @@ impl Crc> { finalize(self.algorithm, crc) } - fn update(&self, mut crc: u8, bytes: &[u8]) -> u8 { - if !SimdValue::is_supported() { + pub(super) fn update(&self, mut crc: u8, bytes: &[u8]) -> u8 { + if !self.algorithm.refin { return update_slice16(crc, &self.table.0, bytes); } + // SAFETY: Both represent numbers let (bytes_before, chunks, bytes_after) = unsafe { bytes.align_to::<[SimdValue; 4]>() }; crc = update_slice16(crc, &self.table.0, bytes_before); if let Some(first_chunk) = chunks.first() { // SAFETY: All required features are supported, by checking SimdValue::is_supported. - crc = unsafe { update_simd(crc as u32, &self.table.1, first_chunk, chunks) } as u8; + crc = + unsafe { crc32_update_refin(crc as u32, &self.table.1, first_chunk, &chunks[1..]) } + as u8; } update_slice16(crc, &self.table.0, bytes_after) } diff --git a/src/lib.rs b/src/lib.rs index 5e11f4f..8b03a84 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,36 +50,88 @@ pub struct Bytewise(core::marker::PhantomData); pub struct NoTable(core::marker::PhantomData); /// Implementation using platform-specific simd instructions. Use it with `Crc>` +#[cfg(all( + target_feature = "sse2", + target_feature = "sse4.1", + target_feature = "pclmulqdq" +))] pub struct Simd(core::marker::PhantomData); +#[cfg(not(all( + target_feature = "sse2", + target_feature = "sse4.1", + target_feature = "pclmulqdq" +)))] +pub type Simd = Slice16; +impl crate::private::Sealed for W {} impl crate::private::Sealed for Slice16 {} impl crate::private::Sealed for Bytewise {} impl crate::private::Sealed for NoTable {} +#[cfg(all( + target_feature = "sse2", + target_feature = "sse4.1", + target_feature = "pclmulqdq" +))] impl crate::private::Sealed for Simd {} -impl crate::Implementation for Slice16 { +impl Implementation for Slice16 { type Width = W; type Table = [[W; 256]; 16]; } -impl crate::Implementation for Bytewise { +impl Implementation for Bytewise { type Width = W; type Table = [W; 256]; } -impl crate::Implementation for NoTable { +impl Implementation for NoTable { type Width = W; type Table = (); } -impl crate::Implementation for Simd { +#[cfg(all( + target_feature = "sse2", + target_feature = "sse4.1", + target_feature = "pclmulqdq" +))] +impl Implementation for Simd { type Width = W; type Table = ([[W; 256]; 16], [simd::SimdValue; 4]); } +#[cfg(feature = "no-table-mem-limit")] +impl Implementation for W { + type Width = W; + type Table = Crc>; +} + +#[cfg(all( + not(feature = "no-table-mem-limit"), + any( + all( + not(feature = "bytewise-mem-limit"), + not(feature = "slice16-mem-limit") + ), + feature = "bytewise-mem-limit" + ) +))] +impl Implementation for W { + type Width = W; + type Table = Crc>; +} + +#[cfg(all( + not(feature = "no-table-mem-limit"), + not(feature = "bytewise-mem-limit"), + feature = "slice16-mem-limit", +))] +impl Implementation for W { + type Width = W; + type Table = Crc>; +} + mod private { pub trait Sealed {} - impl Sealed for W {} } pub trait Implementation: private::Sealed { diff --git a/src/simd.rs b/src/simd.rs index 5b8b3d0..ef8c2ea 100644 --- a/src/simd.rs +++ b/src/simd.rs @@ -1,8 +1,6 @@ mod x86; pub(crate) trait SimdValueOps { - fn is_supported() -> bool; - unsafe fn xor(self, value: u64) -> Self; unsafe fn fold_16(self, x_mod_p: Self, value: Self) -> Self; @@ -15,3 +13,39 @@ pub(crate) trait SimdValueOps { } pub(crate) use x86::SimdValue; + +#[target_feature(enable = "sse2", enable = "sse4.1", enable = "pclmulqdq")] +pub(crate) unsafe fn crc32_update_refin( + crc: u32, + coefficients: &[SimdValue; 4], + first_chunk: &[SimdValue; 4], + chunks: &[[SimdValue; 4]], +) -> u32 { + let mut x4 = *first_chunk; + + // Apply initial crc value + x4[0] = x4[0].xor(crc as u64); + + // Iteratively Fold by 4: + let k1_k2 = coefficients[0]; + for chunk in chunks { + for (x, value) in x4.iter_mut().zip(chunk.iter()) { + *x = x.fold_16(k1_k2, *value) + } + } + + // Iteratively Fold by 1: + let k3_k4 = coefficients[1]; + let mut x = x4[0].fold_16(k3_k4, x4[1]); + x = x.fold_16(k3_k4, x4[2]); + x = x.fold_16(k3_k4, x4[3]); + + // Final Reduction of 128-bits + let k5_k6 = coefficients[2]; + x = x.fold_8(k3_k4); + x = x.fold_4(k5_k6); + + // Barret Reduction + let px_u = coefficients[3]; + x.barret_reduction_32(px_u) +} diff --git a/src/simd/x86.rs b/src/simd/x86.rs index 590ea67..742c866 100644 --- a/src/simd/x86.rs +++ b/src/simd/x86.rs @@ -10,12 +10,6 @@ use core::mem; pub struct SimdValue(arch::__m128i); impl SimdValueOps for SimdValue { - fn is_supported() -> bool { - cfg!(target_feature = "pclmulqdq") - && cfg!(target_feature = "sse2") - && cfg!(target_feature = "sse4.1") - } - #[inline] #[target_feature(enable = "sse2")] unsafe fn xor(self, value: u64) -> Self {