#[cfg(all(target_arch = "x86_64", feature = "avx2"))]
mod avx2;
#[cfg(all(target_arch = "x86_64", feature = "avx512"))]
mod avx512;
mod rust;
#[cfg(test)]
mod tests;
use std::{mem::size_of, num::NonZeroUsize};
use crate::util::Pixel;
pub type SadFn = unsafe fn(
src: *const u8,
src_pitch: NonZeroUsize,
ref_: *const u8,
ref_pitch: NonZeroUsize,
) -> u64;
#[must_use]
#[inline]
pub fn select_sad<T: Pixel>(width: NonZeroUsize, height: NonZeroUsize) -> SadFn {
#[cfg(all(target_arch = "x86_64", feature = "avx512"))]
if crate::util::has_avx512_znver5() {
match (size_of::<T>(), width.get(), height.get()) {
(1, 2, 2) => return avx512::get_sad_u8::<2, 2>,
(1, 2, 4) => return avx512::get_sad_u8::<2, 4>,
(1, 4, 2) => return avx512::get_sad_u8::<4, 2>,
(1, 4, 4) => return avx512::get_sad_u8::<4, 4>,
(1, 4, 8) => return avx512::get_sad_u8::<4, 8>,
(1, 8, 1) => return avx512::get_sad_u8::<8, 1>,
(1, 8, 2) => return avx512::get_sad_u8::<8, 2>,
(1, 8, 4) => return avx512::get_sad_u8::<8, 4>,
(1, 8, 8) => return avx512::get_sad_u8::<8, 8>,
(1, 8, 16) => return avx512::get_sad_u8::<8, 16>,
(1, 16, 1) => return avx512::get_sad_u8::<16, 1>,
(1, 16, 2) => return avx512::get_sad_u8::<16, 2>,
(1, 16, 4) => return avx512::get_sad_u8::<16, 4>,
(1, 16, 8) => return avx512::get_sad_u8::<16, 8>,
(1, 16, 16) => return avx512::get_sad_u8::<16, 16>,
(1, 16, 32) => return avx512::get_sad_u8::<16, 32>,
(1, 32, 8) => return avx512::get_sad_u8::<32, 8>,
(1, 32, 16) => return avx512::get_sad_u8::<32, 16>,
(1, 32, 32) => return avx512::get_sad_u8::<32, 32>,
(1, 32, 64) => return avx512::get_sad_u8::<32, 64>,
(1, 64, 16) => return avx512::get_sad_u8::<64, 16>,
(1, 64, 32) => return avx512::get_sad_u8::<64, 32>,
(1, 64, 64) => return avx512::get_sad_u8::<64, 64>,
(1, 64, 128) => return avx512::get_sad_u8::<64, 128>,
(1, 128, 32) => return avx512::get_sad_u8::<128, 32>,
(1, 128, 64) => return avx512::get_sad_u8::<128, 64>,
(1, 128, 128) => return avx512::get_sad_u8::<128, 128>,
(2, 2, 2) => return avx512::get_sad_u16::<2, 2>,
(2, 2, 4) => return avx512::get_sad_u16::<2, 4>,
(2, 4, 2) => return avx512::get_sad_u16::<4, 2>,
(2, 4, 4) => return avx512::get_sad_u16::<4, 4>,
(2, 4, 8) => return avx512::get_sad_u16::<4, 8>,
(2, 8, 1) => return avx512::get_sad_u16::<8, 1>,
(2, 8, 2) => return avx512::get_sad_u16::<8, 2>,
(2, 8, 4) => return avx512::get_sad_u16::<8, 4>,
(2, 8, 8) => return avx512::get_sad_u16::<8, 8>,
(2, 8, 16) => return avx512::get_sad_u16::<8, 16>,
(2, 16, 1) => return avx512::get_sad_u16::<16, 1>,
(2, 16, 2) => return avx512::get_sad_u16::<16, 2>,
(2, 16, 4) => return avx512::get_sad_u16::<16, 4>,
(2, 16, 8) => return avx512::get_sad_u16::<16, 8>,
(2, 16, 16) => return avx512::get_sad_u16::<16, 16>,
(2, 16, 32) => return avx512::get_sad_u16::<16, 32>,
(2, 32, 8) => return avx512::get_sad_u16::<32, 8>,
(2, 32, 16) => return avx512::get_sad_u16::<32, 16>,
(2, 32, 32) => return avx512::get_sad_u16::<32, 32>,
(2, 32, 64) => return avx512::get_sad_u16::<32, 64>,
(2, 64, 16) => return avx512::get_sad_u16::<64, 16>,
(2, 64, 32) => return avx512::get_sad_u16::<64, 32>,
(2, 64, 64) => return avx512::get_sad_u16::<64, 64>,
(2, 64, 128) => return avx512::get_sad_u16::<64, 128>,
(2, 128, 32) => return avx512::get_sad_u16::<128, 32>,
(2, 128, 64) => return avx512::get_sad_u16::<128, 64>,
(2, 128, 128) => return avx512::get_sad_u16::<128, 128>,
_ => {}
};
}
#[cfg(all(target_arch = "x86_64", feature = "avx512"))]
if crate::util::has_avx512_skylake() {
match (size_of::<T>(), width.get(), height.get()) {
#[cfg(feature = "experimental")]
(1, 2, 2) => return avx512::get_sad_u8::<2, 2>,
#[cfg(feature = "experimental")]
(1, 2, 4) => return avx512::get_sad_u8::<2, 4>,
(1, 4, 2) => return avx512::get_sad_u8::<4, 2>,
(1, 4, 4) => return avx512::get_sad_u8::<4, 4>,
(1, 4, 8) => return avx512::get_sad_u8::<4, 8>,
(1, 8, 1) => return avx512::get_sad_u8::<8, 1>,
(1, 8, 2) => return avx512::get_sad_u8::<8, 2>,
(1, 8, 4) => return avx512::get_sad_u8::<8, 4>,
(1, 8, 8) => return avx512::get_sad_u8::<8, 8>,
(1, 8, 16) => return avx512::get_sad_u8::<8, 16>,
(1, 16, 1) => return avx512::get_sad_u8::<16, 1>,
(1, 16, 2) => return avx512::get_sad_u8::<16, 2>,
(1, 16, 4) => return avx512::get_sad_u8::<16, 4>,
(1, 16, 8) => return avx512::get_sad_u8::<16, 8>,
(1, 16, 16) => return avx512::get_sad_u8::<16, 16>,
(1, 16, 32) => return avx512::get_sad_u8::<16, 32>,
#[cfg(feature = "experimental")]
(1, 32, 8) => return avx512::get_sad_u8::<32, 8>,
#[cfg(feature = "experimental")]
(1, 32, 16) => return avx512::get_sad_u8::<32, 16>,
#[cfg(feature = "experimental")]
(1, 32, 32) => return avx512::get_sad_u8::<32, 32>,
#[cfg(feature = "experimental")]
(1, 32, 64) => return avx512::get_sad_u8::<32, 64>,
#[cfg(feature = "experimental")]
(1, 64, 16) => return avx512::get_sad_u8::<64, 16>,
#[cfg(feature = "experimental")]
(1, 64, 32) => return avx512::get_sad_u8::<64, 32>,
#[cfg(feature = "experimental")]
(1, 64, 64) => return avx512::get_sad_u8::<64, 64>,
#[cfg(feature = "experimental")]
(1, 64, 128) => return avx512::get_sad_u8::<64, 128>,
#[cfg(feature = "experimental")]
(1, 128, 32) => return avx512::get_sad_u8::<128, 32>,
#[cfg(feature = "experimental")]
(1, 128, 64) => return avx512::get_sad_u8::<128, 64>,
#[cfg(feature = "experimental")]
(1, 128, 128) => return avx512::get_sad_u8::<128, 128>,
#[cfg(feature = "experimental")]
(2, 2, 2) => return avx512::get_sad_u16::<2, 2>,
#[cfg(feature = "experimental")]
(2, 2, 4) => return avx512::get_sad_u16::<2, 4>,
(2, 4, 2) => return avx512::get_sad_u16::<4, 2>,
(2, 4, 4) => return avx512::get_sad_u16::<4, 4>,
(2, 4, 8) => return avx512::get_sad_u16::<4, 8>,
(2, 8, 1) => return avx512::get_sad_u16::<8, 1>,
(2, 8, 2) => return avx512::get_sad_u16::<8, 2>,
(2, 8, 4) => return avx512::get_sad_u16::<8, 4>,
(2, 8, 8) => return avx512::get_sad_u16::<8, 8>,
(2, 8, 16) => return avx512::get_sad_u16::<8, 16>,
#[cfg(feature = "experimental")]
(2, 16, 1) => return avx512::get_sad_u16::<16, 1>,
#[cfg(feature = "experimental")]
(2, 16, 2) => return avx512::get_sad_u16::<16, 2>,
#[cfg(feature = "experimental")]
(2, 16, 4) => return avx512::get_sad_u16::<16, 4>,
#[cfg(feature = "experimental")]
(2, 16, 8) => return avx512::get_sad_u16::<16, 8>,
#[cfg(feature = "experimental")]
(2, 16, 16) => return avx512::get_sad_u16::<16, 16>,
#[cfg(feature = "experimental")]
(2, 16, 32) => return avx512::get_sad_u16::<16, 32>,
(2, 32, 8) => return avx512::get_sad_u16::<32, 8>,
(2, 32, 16) => return avx512::get_sad_u16::<32, 16>,
(2, 32, 32) => return avx512::get_sad_u16::<32, 32>,
(2, 32, 64) => return avx512::get_sad_u16::<32, 64>,
(2, 64, 16) => return avx512::get_sad_u16::<64, 16>,
(2, 64, 32) => return avx512::get_sad_u16::<64, 32>,
(2, 64, 64) => return avx512::get_sad_u16::<64, 64>,
(2, 64, 128) => return avx512::get_sad_u16::<64, 128>,
(2, 128, 32) => return avx512::get_sad_u16::<128, 32>,
(2, 128, 64) => return avx512::get_sad_u16::<128, 64>,
(2, 128, 128) => return avx512::get_sad_u16::<128, 128>,
_ => {}
};
}
#[cfg(all(target_arch = "x86_64", feature = "avx2"))]
if crate::util::has_avx2() {
match (size_of::<T>(), width.get(), height.get()) {
#[cfg(feature = "experimental")]
(1, 2, 2) => return avx2::get_sad_u8::<2, 2>,
#[cfg(feature = "experimental")]
(1, 2, 4) => return avx2::get_sad_u8::<2, 4>,
(1, 4, 2) => return avx2::get_sad_u8::<4, 2>,
(1, 4, 4) => return avx2::get_sad_u8::<4, 4>,
(1, 4, 8) => return avx2::get_sad_u8::<4, 8>,
(1, 8, 1) => return avx2::get_sad_u8::<8, 1>,
(1, 8, 2) => return avx2::get_sad_u8::<8, 2>,
(1, 8, 4) => return avx2::get_sad_u8::<8, 4>,
(1, 8, 8) => return avx2::get_sad_u8::<8, 8>,
(1, 8, 16) => return avx2::get_sad_u8::<8, 16>,
(1, 16, 1) => return avx2::get_sad_u8::<16, 1>,
(1, 16, 2) => return avx2::get_sad_u8::<16, 2>,
(1, 16, 4) => return avx2::get_sad_u8::<16, 4>,
(1, 16, 8) => return avx2::get_sad_u8::<16, 8>,
(1, 16, 16) => return avx2::get_sad_u8::<16, 16>,
(1, 16, 32) => return avx2::get_sad_u8::<16, 32>,
(1, 32, 8) => return avx2::get_sad_u8::<32, 8>,
(1, 32, 16) => return avx2::get_sad_u8::<32, 16>,
(1, 32, 32) => return avx2::get_sad_u8::<32, 32>,
(1, 32, 64) => return avx2::get_sad_u8::<32, 64>,
(1, 64, 16) => return avx2::get_sad_u8::<64, 16>,
(1, 64, 32) => return avx2::get_sad_u8::<64, 32>,
(1, 64, 64) => return avx2::get_sad_u8::<64, 64>,
(1, 64, 128) => return avx2::get_sad_u8::<64, 128>,
(1, 128, 32) => return avx2::get_sad_u8::<128, 32>,
(1, 128, 64) => return avx2::get_sad_u8::<128, 64>,
(1, 128, 128) => return avx2::get_sad_u8::<128, 128>,
#[cfg(feature = "experimental")]
(2, 2, 2) => return avx2::get_sad_u16::<2, 2>,
#[cfg(feature = "experimental")]
(2, 2, 4) => return avx2::get_sad_u16::<2, 4>,
(2, 4, 2) => return avx2::get_sad_u16::<4, 2>,
(2, 4, 4) => return avx2::get_sad_u16::<4, 4>,
(2, 4, 8) => return avx2::get_sad_u16::<4, 8>,
(2, 8, 1) => return avx2::get_sad_u16::<8, 1>,
(2, 8, 2) => return avx2::get_sad_u16::<8, 2>,
(2, 8, 4) => return avx2::get_sad_u16::<8, 4>,
(2, 8, 8) => return avx2::get_sad_u16::<8, 8>,
(2, 8, 16) => return avx2::get_sad_u16::<8, 16>,
(2, 16, 1) => return avx2::get_sad_u16::<16, 1>,
(2, 16, 2) => return avx2::get_sad_u16::<16, 2>,
(2, 16, 4) => return avx2::get_sad_u16::<16, 4>,
(2, 16, 8) => return avx2::get_sad_u16::<16, 8>,
(2, 16, 16) => return avx2::get_sad_u16::<16, 16>,
(2, 16, 32) => return avx2::get_sad_u16::<16, 32>,
(2, 32, 8) => return avx2::get_sad_u16::<32, 8>,
(2, 32, 16) => return avx2::get_sad_u16::<32, 16>,
(2, 32, 32) => return avx2::get_sad_u16::<32, 32>,
(2, 32, 64) => return avx2::get_sad_u16::<32, 64>,
(2, 64, 16) => return avx2::get_sad_u16::<64, 16>,
(2, 64, 32) => return avx2::get_sad_u16::<64, 32>,
(2, 64, 64) => return avx2::get_sad_u16::<64, 64>,
(2, 64, 128) => return avx2::get_sad_u16::<64, 128>,
(2, 128, 32) => return avx2::get_sad_u16::<128, 32>,
(2, 128, 64) => return avx2::get_sad_u16::<128, 64>,
(2, 128, 128) => return avx2::get_sad_u16::<128, 128>,
_ => {}
};
}
match (size_of::<T>(), width.get(), height.get()) {
(1, 2, 2) => rust::get_sad_u8::<2, 2>,
(1, 2, 4) => rust::get_sad_u8::<2, 4>,
(1, 4, 2) => rust::get_sad_u8::<4, 2>,
(1, 4, 4) => rust::get_sad_u8::<4, 4>,
(1, 4, 8) => rust::get_sad_u8::<4, 8>,
(1, 8, 1) => rust::get_sad_u8::<8, 1>,
(1, 8, 2) => rust::get_sad_u8::<8, 2>,
(1, 8, 4) => rust::get_sad_u8::<8, 4>,
(1, 8, 8) => rust::get_sad_u8::<8, 8>,
(1, 8, 16) => rust::get_sad_u8::<8, 16>,
(1, 16, 1) => rust::get_sad_u8::<16, 1>,
(1, 16, 2) => rust::get_sad_u8::<16, 2>,
(1, 16, 4) => rust::get_sad_u8::<16, 4>,
(1, 16, 8) => rust::get_sad_u8::<16, 8>,
(1, 16, 16) => rust::get_sad_u8::<16, 16>,
(1, 16, 32) => rust::get_sad_u8::<16, 32>,
(1, 32, 8) => rust::get_sad_u8::<32, 8>,
(1, 32, 16) => rust::get_sad_u8::<32, 16>,
(1, 32, 32) => rust::get_sad_u8::<32, 32>,
(1, 32, 64) => rust::get_sad_u8::<32, 64>,
(1, 64, 16) => rust::get_sad_u8::<64, 16>,
(1, 64, 32) => rust::get_sad_u8::<64, 32>,
(1, 64, 64) => rust::get_sad_u8::<64, 64>,
(1, 64, 128) => rust::get_sad_u8::<64, 128>,
(1, 128, 32) => rust::get_sad_u8::<128, 32>,
(1, 128, 64) => rust::get_sad_u8::<128, 64>,
(1, 128, 128) => rust::get_sad_u8::<128, 128>,
(2, 2, 2) => rust::get_sad_u16::<2, 2>,
(2, 2, 4) => rust::get_sad_u16::<2, 4>,
(2, 4, 2) => rust::get_sad_u16::<4, 2>,
(2, 4, 4) => rust::get_sad_u16::<4, 4>,
(2, 4, 8) => rust::get_sad_u16::<4, 8>,
(2, 8, 1) => rust::get_sad_u16::<8, 1>,
(2, 8, 2) => rust::get_sad_u16::<8, 2>,
(2, 8, 4) => rust::get_sad_u16::<8, 4>,
(2, 8, 8) => rust::get_sad_u16::<8, 8>,
(2, 8, 16) => rust::get_sad_u16::<8, 16>,
(2, 16, 1) => rust::get_sad_u16::<16, 1>,
(2, 16, 2) => rust::get_sad_u16::<16, 2>,
(2, 16, 4) => rust::get_sad_u16::<16, 4>,
(2, 16, 8) => rust::get_sad_u16::<16, 8>,
(2, 16, 16) => rust::get_sad_u16::<16, 16>,
(2, 16, 32) => rust::get_sad_u16::<16, 32>,
(2, 32, 8) => rust::get_sad_u16::<32, 8>,
(2, 32, 16) => rust::get_sad_u16::<32, 16>,
(2, 32, 32) => rust::get_sad_u16::<32, 32>,
(2, 32, 64) => rust::get_sad_u16::<32, 64>,
(2, 64, 16) => rust::get_sad_u16::<64, 16>,
(2, 64, 32) => rust::get_sad_u16::<64, 32>,
(2, 64, 64) => rust::get_sad_u16::<64, 64>,
(2, 64, 128) => rust::get_sad_u16::<64, 128>,
(2, 128, 32) => rust::get_sad_u16::<128, 32>,
(2, 128, 64) => rust::get_sad_u16::<128, 64>,
(2, 128, 128) => rust::get_sad_u16::<128, 128>,
_ => panic!("unsupported block size for SAD: {}x{}", width, height),
}
}