#![allow(clippy::unwrap_used, reason = "allow in test files")]
#![allow(clippy::undocumented_unsafe_blocks, reason = "allow in test files")]
#![allow(clippy::indexing_slicing, reason = "allow in test files")]
#![allow(unused_unsafe)]
use std::num::NonZeroUsize;
use crate::tests::should_run;
use pastey::paste;
const SAD_SIZES: &[(usize, usize)] = &[
(2, 2),
(2, 4),
(4, 2),
(4, 4),
(4, 8),
(8, 1),
(8, 2),
(8, 4),
(8, 8),
(8, 16),
(16, 1),
(16, 2),
(16, 4),
(16, 8),
(16, 16),
(16, 32),
(32, 8),
(32, 16),
(32, 32),
(32, 64),
(64, 16),
(64, 32),
(64, 64),
(64, 128),
(128, 32),
(128, 64),
(128, 128),
];
macro_rules! get_sad_tests {
($module:ident) => {
paste! {
#[test]
fn [<sad_identical_u8_ $module>]() {
if !should_run(stringify!($module)) {
return;
}
for &(w, h) in SAD_SIZES {
let width = NonZeroUsize::new(w).unwrap();
let height = NonZeroUsize::new(h).unwrap();
let src: Vec<u8> = vec![42u8; w * h];
let ref_: Vec<u8> = vec![42u8; w * h];
let pitch = NonZeroUsize::new(w).unwrap();
let result = unsafe { verify_asm!(ret $module, get_sad(width, height, &src, pitch, &ref_, pitch)) };
assert_eq!(result, 0, "failed at {w}x{h}");
}
}
#[test]
fn [<sad_identical_u16_ $module>]() {
if !should_run(stringify!($module)) {
return;
}
for &(w, h) in SAD_SIZES {
let width = NonZeroUsize::new(w).unwrap();
let height = NonZeroUsize::new(h).unwrap();
let src: Vec<u16> = vec![1000u16; w * h];
let ref_: Vec<u16> = vec![1000u16; w * h];
let pitch = NonZeroUsize::new(w).unwrap();
let result = unsafe { verify_asm!(ret $module, get_sad(width, height, &src, pitch, &ref_, pitch)) };
assert_eq!(result, 0, "failed at {w}x{h}");
}
}
#[test]
fn [<sad_uniform_diff_u8_ $module>]() {
if !should_run(stringify!($module)) {
return;
}
for &(w, h) in SAD_SIZES {
let width = NonZeroUsize::new(w).unwrap();
let height = NonZeroUsize::new(h).unwrap();
let src: Vec<u8> = vec![10u8; w * h];
let ref_: Vec<u8> = vec![7u8; w * h];
let pitch = NonZeroUsize::new(w).unwrap();
let result = unsafe { verify_asm!(ret $module, get_sad(width, height, &src, pitch, &ref_, pitch)) };
assert_eq!(result, 3 * (w * h) as u64, "failed at {w}x{h}");
}
}
#[test]
fn [<sad_uniform_diff_u16_ $module>]() {
if !should_run(stringify!($module)) {
return;
}
for &(w, h) in SAD_SIZES {
let width = NonZeroUsize::new(w).unwrap();
let height = NonZeroUsize::new(h).unwrap();
let src: Vec<u16> = vec![1000u16; w * h];
let ref_: Vec<u16> = vec![700u16; w * h];
let pitch = NonZeroUsize::new(w).unwrap();
let result = unsafe { verify_asm!(ret $module, get_sad(width, height, &src, pitch, &ref_, pitch)) };
assert_eq!(result, 300 * (w * h) as u64, "failed at {w}x{h}");
}
}
#[test]
fn [<sad_with_padding_u8_ $module>]() {
if !should_run(stringify!($module)) {
return;
}
for &(w, h) in SAD_SIZES {
let padding = 16;
let pitch = w + padding;
let mut src: Vec<u8> = vec![255u8; pitch * h];
let mut ref_: Vec<u8> = vec![255u8; pitch * h];
for row in 0..h {
for col in 0..w {
src[row * pitch + col] = 10;
ref_[row * pitch + col] = 7;
}
}
let width = NonZeroUsize::new(w).unwrap();
let height = NonZeroUsize::new(h).unwrap();
let src_pitch = NonZeroUsize::new(pitch).unwrap();
let result = unsafe { verify_asm!(ret $module, get_sad(width, height, &src, src_pitch, &ref_, src_pitch)) };
assert_eq!(result, 3 * (w * h) as u64, "failed at {w}x{h}");
}
}
#[test]
fn [<sad_with_padding_u16_ $module>]() {
if !should_run(stringify!($module)) {
return;
}
for &(w, h) in SAD_SIZES {
let padding = 16;
let pitch = w + padding;
let mut src: Vec<u16> = vec![65535u16; pitch * h];
let mut ref_: Vec<u16> = vec![65535u16; pitch * h];
for row in 0..h {
for col in 0..w {
src[row * pitch + col] = 1000;
ref_[row * pitch + col] = 700;
}
}
let width = NonZeroUsize::new(w).unwrap();
let height = NonZeroUsize::new(h).unwrap();
let src_pitch = NonZeroUsize::new(pitch).unwrap();
let result = unsafe { verify_asm!(ret $module, get_sad(width, height, &src, src_pitch, &ref_, src_pitch)) };
assert_eq!(result, 300 * (w * h) as u64, "failed at {w}x{h}");
}
}
#[test]
fn [<sad_zeros_u8_ $module>]() {
if !should_run(stringify!($module)) {
return;
}
let w = 8;
let h = 8;
let src: Vec<u8> = vec![0u8; w * h];
let ref_: Vec<u8> = vec![0u8; w * h];
let width = NonZeroUsize::new(w).unwrap();
let height = NonZeroUsize::new(h).unwrap();
let pitch = NonZeroUsize::new(w).unwrap();
let result = unsafe { verify_asm!(ret $module, get_sad(width, height, &src, pitch, &ref_, pitch)) };
assert_eq!(result, 0);
}
#[test]
fn [<sad_one_side_zero_u8_ $module>]() {
if !should_run(stringify!($module)) {
return;
}
let w = 8;
let h = 8;
let src: Vec<u8> = vec![5u8; w * h];
let ref_: Vec<u8> = vec![0u8; w * h];
let width = NonZeroUsize::new(w).unwrap();
let height = NonZeroUsize::new(h).unwrap();
let pitch = NonZeroUsize::new(w).unwrap();
let result = unsafe { verify_asm!(ret $module, get_sad(width, height, &src, pitch, &ref_, pitch)) };
assert_eq!(result, 5 * (w * h) as u64);
}
#[test]
fn [<sad_max_u16_ $module>]() {
if !should_run(stringify!($module)) {
return;
}
let w = 128;
let h = 128;
let src: Vec<u16> = vec![u16::MAX; w * h];
let ref_: Vec<u16> = vec![0u16; w * h];
let width = NonZeroUsize::new(w).unwrap();
let height = NonZeroUsize::new(h).unwrap();
let pitch = NonZeroUsize::new(w).unwrap();
let result = unsafe { verify_asm!(ret $module, get_sad(width, height, &src, pitch, &ref_, pitch)) };
assert_eq!(result, u16::MAX as u64 * (w * h) as u64);
}
#[test]
fn [<sad_sequential_u8_ $module>]() {
if !should_run(stringify!($module)) {
return;
}
let w = 4;
let h = 4;
let src: Vec<u8> = (1..=16).collect();
let ref_: Vec<u8> = (16..=31).collect();
let width = NonZeroUsize::new(w).unwrap();
let height = NonZeroUsize::new(h).unwrap();
let pitch = NonZeroUsize::new(w).unwrap();
let result = unsafe { verify_asm!(ret $module, get_sad(width, height, &src, pitch, &ref_, pitch)) };
assert_eq!(result, 240);
}
#[test]
fn [<sad_sequential_u16_ $module>]() {
if !should_run(stringify!($module)) {
return;
}
let w = 4;
let h = 4;
let src: Vec<u16> = (1000..=1015).collect();
let ref_: Vec<u16> = (2000..=2015).collect();
let width = NonZeroUsize::new(w).unwrap();
let height = NonZeroUsize::new(h).unwrap();
let pitch = NonZeroUsize::new(w).unwrap();
let result = unsafe { verify_asm!(ret $module, get_sad(width, height, &src, pitch, &ref_, pitch)) };
assert_eq!(result, 16000);
}
}
};
}
get_sad_tests!(rust);
#[cfg(all(target_arch = "x86_64", feature = "simd"))]
get_sad_tests!(avx2);
#[cfg(all(target_arch = "x86_64", feature = "simd"))]
get_sad_tests!(avx512);