use crate::{Alphabet, EncodeError, scalar, scalar_encode_in_place};
const MIN_SIMD_ENCODE_BLOCK: usize = 12;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum EncodeBackend {
Scalar,
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
Avx512Vbmi,
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
Avx2,
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
Ssse3Sse41,
#[cfg(all(feature = "simd", feature = "std", target_arch = "aarch64"))]
Neon,
}
#[must_use]
pub(crate) fn active_encode_backend() -> EncodeBackend {
#[cfg(feature = "simd")]
match crate::simd::active_backend() {
crate::simd::ActiveBackend::Scalar => {}
#[cfg(all(feature = "std", any(target_arch = "x86", target_arch = "x86_64")))]
crate::simd::ActiveBackend::Avx512Vbmi => return EncodeBackend::Avx512Vbmi,
#[cfg(all(feature = "std", any(target_arch = "x86", target_arch = "x86_64")))]
crate::simd::ActiveBackend::Avx2 => return EncodeBackend::Avx2,
#[cfg(all(feature = "std", any(target_arch = "x86", target_arch = "x86_64")))]
crate::simd::ActiveBackend::Ssse3Sse41 => return EncodeBackend::Ssse3Sse41,
#[cfg(all(feature = "std", target_arch = "aarch64"))]
crate::simd::ActiveBackend::Neon => return EncodeBackend::Neon,
}
EncodeBackend::Scalar
}
pub(crate) fn encode_slice<A, const PAD: bool>(
input: &[u8],
output: &mut [u8],
) -> Result<usize, EncodeError>
where
A: Alphabet,
{
if input.len() < MIN_SIMD_ENCODE_BLOCK {
return scalar::encode_slice::<A, PAD>(input, output);
}
match active_encode_backend() {
EncodeBackend::Scalar => scalar::encode_slice::<A, PAD>(input, output),
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
EncodeBackend::Avx512Vbmi => {
if input.len() >= 48 && crate::simd::avx512_supports_alphabet::<A>() {
crate::simd::encode_slice_avx512::<A, PAD>(input, output)
} else {
scalar::encode_slice::<A, PAD>(input, output)
}
}
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
EncodeBackend::Avx2 => {
if input.len() >= 24 && crate::simd::avx2_supports_alphabet::<A>() {
crate::simd::encode_slice_avx2::<A, PAD>(input, output)
} else {
scalar::encode_slice::<A, PAD>(input, output)
}
}
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
EncodeBackend::Ssse3Sse41 => {
if input.len() >= 12 && crate::simd::ssse3_sse41_supports_alphabet::<A>() {
crate::simd::encode_slice_ssse3_sse41::<A, PAD>(input, output)
} else {
scalar::encode_slice::<A, PAD>(input, output)
}
}
#[cfg(all(feature = "simd", feature = "std", target_arch = "aarch64"))]
EncodeBackend::Neon => {
if input.len() >= 12 && crate::simd::neon_supports_alphabet::<A>() {
crate::simd::encode_slice_neon::<A, PAD>(input, output)
} else {
scalar::encode_slice::<A, PAD>(input, output)
}
}
}
}
pub(crate) fn encode_in_place<A, const PAD: bool>(
buffer: &mut [u8],
input_len: usize,
) -> Result<usize, EncodeError>
where
A: Alphabet,
{
match active_encode_backend() {
EncodeBackend::Scalar => {
scalar_encode_in_place::encode_in_place::<A, PAD>(buffer, input_len)
}
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
EncodeBackend::Avx512Vbmi => {
scalar_encode_in_place::encode_in_place::<A, PAD>(buffer, input_len)
}
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
EncodeBackend::Avx2 => scalar_encode_in_place::encode_in_place::<A, PAD>(buffer, input_len),
#[cfg(all(
feature = "simd",
feature = "std",
any(target_arch = "x86", target_arch = "x86_64")
))]
EncodeBackend::Ssse3Sse41 => {
scalar_encode_in_place::encode_in_place::<A, PAD>(buffer, input_len)
}
#[cfg(all(feature = "simd", feature = "std", target_arch = "aarch64"))]
EncodeBackend::Neon => scalar_encode_in_place::encode_in_place::<A, PAD>(buffer, input_len),
}
}