#[cfg(feature = "simd")]
use packed_simd_2::*;
#[cfg(feature = "simd")]
fn abs(v: i16x4) -> i16x4 {
let mask = v >> 15;
(v + mask) ^ mask
}
#[cfg(feature = "simd")]
fn if_then_else(c: i16x4, t: i16x4, e: i16x4) -> i16x4 {
(c & t) | (e & !c)
}
fn paeth(a: u8, b: u8, c: u8) -> u8 {
let (a, b, c) = (a as i16, b as i16, c as i16);
let mut pa = b - c;
let mut pb = a - c;
let mut pc = pa + pb;
pa = pa.abs();
pb = pb.abs();
pc = pc.abs();
(if pa <= pb && pa <= pc {
a
} else if pb <= pa && pb <= pc {
b
} else {
c
} as u8)
}
#[allow(clippy::many_single_char_names)]
pub fn filter(size: (usize, usize), pixel_size: usize, pixels: &mut [u8], old_pixels: &mut [u8]) {
assert!(size.0 < u32::MAX as usize);
assert!(size.1 < u32::MAX as usize);
assert!(pixel_size < u8::MAX as usize);
assert_eq!(pixels.len(), size.0 * size.1 * pixel_size);
assert_eq!(pixels.len(), old_pixels.len());
for i in (size.0 * pixel_size..pixels.len()).rev() {
let z = unsafe { old_pixels.get_unchecked_mut(i) };
let a = *unsafe { pixels.get_unchecked(i - pixel_size) };
let b = *unsafe { pixels.get_unchecked(i - size.0 * pixel_size) };
let c = *unsafe { pixels.get_unchecked(i - (size.0 - 1) * pixel_size) };
let x = unsafe { pixels.get_unchecked_mut(i) };
let old_z = *z;
*z = x.wrapping_sub(paeth(a, b, c));
*x = z.wrapping_sub(old_z);
}
for i in (pixel_size..size.0 * pixel_size).rev() {
let z = unsafe { old_pixels.get_unchecked_mut(i) };
let a = *unsafe { pixels.get_unchecked(i - pixel_size) };
let x = unsafe { pixels.get_unchecked_mut(i) };
let old_z = *z;
*z = x.wrapping_sub(a);
*x = z.wrapping_sub(old_z);
}
if !pixels.is_empty() {
for i in 0..pixel_size {
let z = unsafe { old_pixels.get_unchecked_mut(i) };
let x = unsafe { pixels.get_unchecked_mut(i) };
let old_z = *z;
*z = *x;
*x = x.wrapping_sub(old_z);
}
}
}
#[cfg(feature = "simd")]
#[allow(clippy::many_single_char_names)]
pub fn filter_simd_4(
size: (usize, usize),
pixel_size: usize,
pixels: &mut [u8],
old_pixels: &mut [u8],
) {
assert!(size.0 < u32::MAX as usize);
assert!(size.1 < u32::MAX as usize);
assert_eq!(pixel_size % 4, 0);
assert!(pixel_size < u8::MAX as usize);
assert_eq!(pixels.len(), size.0 * size.1 * pixel_size);
assert_eq!(pixels.len(), old_pixels.len());
for i in (size.0 * pixel_size..pixels.len()).step_by(4).rev() {
let a = i16x4::from(unsafe {
u8x4::from_slice_unaligned_unchecked(
pixels.get_unchecked(i - pixel_size..i - pixel_size + 4),
)
});
let b = i16x4::from(unsafe {
u8x4::from_slice_unaligned_unchecked(
pixels.get_unchecked(i - size.0 * pixel_size..i - size.0 * pixel_size + 4),
)
});
let c =
i16x4::from(unsafe {
u8x4::from_slice_unaligned_unchecked(pixels.get_unchecked(
i - (size.0 - 1) * pixel_size..i - (size.0 - 1) * pixel_size + 4,
))
});
let mut pa = b - c;
let mut pb = a - c;
let mut pc = pa + pb;
pa = abs(pa);
pb = abs(pb);
pc = abs(pc);
let smallest = pa.min(pb).min(pc);
let nearest = u8x4::from_cast(if_then_else(
i16x4::from_cast(smallest.eq(pa)),
a,
if_then_else(i16x4::from_cast(smallest.eq(pb)), b, c),
));
let z = unsafe { old_pixels.get_unchecked_mut(i..i + 4) };
let x = unsafe { pixels.get_unchecked_mut(i..i + 4) };
let old_zv = unsafe { u8x4::from_slice_unaligned_unchecked(z) };
let xv = unsafe { u8x4::from_slice_unaligned_unchecked(x) };
let zv = xv - nearest;
unsafe {
zv.write_to_slice_unaligned_unchecked(z);
(zv - old_zv).write_to_slice_unaligned_unchecked(x)
};
}
for i in (pixel_size..size.0 * pixel_size).step_by(4).rev() {
let a = unsafe {
u8x4::from_slice_unaligned_unchecked(
pixels.get_unchecked(i - pixel_size..i - pixel_size + 4),
)
};
let z = unsafe { old_pixels.get_unchecked_mut(i..i + 4) };
let x = unsafe { pixels.get_unchecked_mut(i..i + 4) };
let old_zv = unsafe { u8x4::from_slice_unaligned_unchecked(z) };
let xv = unsafe { u8x4::from_slice_unaligned_unchecked(x) };
let zv = xv - a;
unsafe {
zv.write_to_slice_unaligned_unchecked(z);
(zv - old_zv).write_to_slice_unaligned_unchecked(x);
}
}
if !pixels.is_empty() {
let z = unsafe { old_pixels.get_unchecked_mut(0..4) };
let x = unsafe { pixels.get_unchecked_mut(0..4) };
let old_zv = unsafe { u8x4::from_slice_unaligned_unchecked(z) };
let xv = unsafe { u8x4::from_slice_unaligned_unchecked(x) };
unsafe {
xv.write_to_slice_unaligned_unchecked(z);
(xv - old_zv).write_to_slice_unaligned_unchecked(x);
}
}
}
#[cfg(feature = "simd")]
#[allow(clippy::many_single_char_names)]
pub fn filter_simd_3(
size: (usize, usize),
pixel_size: usize,
pixels: &mut [u8],
old_pixels: &mut [u8],
) {
assert!(size.0 < u32::MAX as usize);
assert!(size.1 < u32::MAX as usize);
assert_eq!(pixel_size % 3, 0);
assert!(pixel_size < u8::MAX as usize);
assert_eq!(pixels.len(), size.0 * size.1 * pixel_size);
assert_eq!(pixels.len(), old_pixels.len());
for i in (size.0 * pixel_size..pixels.len()).step_by(3).rev() {
let a = i16x4::from(unsafe {
u8x4::from_slice_unaligned_unchecked(
pixels.get_unchecked(i - pixel_size..i - pixel_size + 4),
)
});
let b = i16x4::from(unsafe {
u8x4::from_slice_unaligned_unchecked(
pixels.get_unchecked(i - size.0 * pixel_size..i - size.0 * pixel_size + 4),
)
});
let c =
i16x4::from(unsafe {
u8x4::from_slice_unaligned_unchecked(pixels.get_unchecked(
i - (size.0 - 1) * pixel_size..i - (size.0 - 1) * pixel_size + 4,
))
});
let mut pa = b - c;
let mut pb = a - c;
let mut pc = pa + pb;
pa = abs(pa);
pb = abs(pb);
pc = abs(pc);
let smallest = pa.min(pb).min(pc);
let nearest = u8x4::from_cast(if_then_else(
i16x4::from_cast(smallest.eq(pa)),
a,
if_then_else(i16x4::from_cast(smallest.eq(pb)), b, c),
));
let z = unsafe { old_pixels.get_unchecked_mut(i..i + 4) };
let x = unsafe { pixels.get_unchecked_mut(i..i + 4) };
let old_zv = unsafe { u8x4::from_slice_unaligned_unchecked(z) };
let xv = unsafe { u8x4::from_slice_unaligned_unchecked(x) };
let mut zv = xv - nearest;
z[0] = unsafe { zv.extract_unchecked(0) };
z[1] = unsafe { zv.extract_unchecked(1) };
z[2] = unsafe { zv.extract_unchecked(2) };
zv -= old_zv;
x[0] = unsafe { zv.extract_unchecked(0) };
x[1] = unsafe { zv.extract_unchecked(1) };
x[2] = unsafe { zv.extract_unchecked(2) };
}
for i in (pixel_size..size.0 * pixel_size).step_by(3).rev() {
let a = unsafe {
u8x4::from_slice_unaligned_unchecked(
pixels.get_unchecked(i - pixel_size..i - pixel_size + 4),
)
};
let z = unsafe { old_pixels.get_unchecked_mut(i..i + 4) };
let x = unsafe { pixels.get_unchecked_mut(i..i + 4) };
let old_zv = unsafe { u8x4::from_slice_unaligned_unchecked(z) };
let xv = unsafe { u8x4::from_slice_unaligned_unchecked(x) };
let mut zv = xv - a;
z[0] = unsafe { zv.extract_unchecked(0) };
z[1] = unsafe { zv.extract_unchecked(1) };
z[2] = unsafe { zv.extract_unchecked(2) };
zv -= old_zv;
x[0] = unsafe { zv.extract_unchecked(0) };
x[1] = unsafe { zv.extract_unchecked(1) };
x[2] = unsafe { zv.extract_unchecked(2) };
}
if !pixels.is_empty() {
let z = unsafe { old_pixels.get_unchecked_mut(0..4) };
let x = unsafe { pixels.get_unchecked_mut(0..4) };
let old_zv = unsafe { u8x4::from_slice_unaligned_unchecked(z) };
let mut xv = unsafe { u8x4::from_slice_unaligned_unchecked(x) };
z[0] = unsafe { xv.extract_unchecked(0) };
z[1] = unsafe { xv.extract_unchecked(1) };
z[2] = unsafe { xv.extract_unchecked(2) };
xv -= old_zv;
x[0] = unsafe { xv.extract_unchecked(0) };
x[1] = unsafe { xv.extract_unchecked(1) };
x[2] = unsafe { xv.extract_unchecked(2) };
}
}
#[allow(clippy::many_single_char_names)]
pub fn unfilter(size: (usize, usize), pixel_size: usize, pixels: &mut [u8], old_pixels: &mut [u8]) {
assert!(size.0 < u32::MAX as usize);
assert!(size.1 < u32::MAX as usize);
assert!(pixel_size < u8::MAX as usize);
assert_eq!(pixels.len(), size.0 * size.1 * pixel_size);
assert_eq!(pixels.len(), old_pixels.len());
if !pixels.is_empty() {
for i in 0..pixel_size {
let z = unsafe { old_pixels.get_unchecked_mut(i) };
let x = unsafe { pixels.get_unchecked_mut(i) };
*z = z.wrapping_add(*x);
*x = *z;
}
}
for i in pixel_size..size.0 * pixel_size {
let z = unsafe { old_pixels.get_unchecked_mut(i) };
let a = *unsafe { pixels.get_unchecked(i - pixel_size) };
let x = unsafe { pixels.get_unchecked_mut(i) };
*z = z.wrapping_add(*x);
*x = z.wrapping_add(a);
}
for i in size.0 * pixel_size..pixels.len() {
let z = unsafe { old_pixels.get_unchecked_mut(i) };
let a = *unsafe { pixels.get_unchecked(i - pixel_size) };
let b = *unsafe { pixels.get_unchecked(i - size.0 * pixel_size) };
let c = *unsafe { pixels.get_unchecked(i - (size.0 - 1) * pixel_size) };
let x = unsafe { pixels.get_unchecked_mut(i) };
*z = z.wrapping_add(*x);
*x = z.wrapping_add(paeth(a, b, c));
}
}
#[cfg(feature = "simd")]
#[allow(clippy::many_single_char_names)]
pub fn unfilter_simd_4(
size: (usize, usize),
pixel_size: usize,
pixels: &mut [u8],
old_pixels: &mut [u8],
) {
assert!(size.0 < u32::MAX as usize);
assert!(size.1 < u32::MAX as usize);
assert_eq!(pixel_size % 4, 0);
assert!(pixel_size < u8::MAX as usize);
assert_eq!(pixels.len(), size.0 * size.1 * pixel_size);
assert_eq!(pixels.len(), old_pixels.len());
if !pixels.is_empty() {
let z = unsafe { old_pixels.get_unchecked_mut(0..4) };
let x = unsafe { pixels.get_unchecked_mut(0..4) };
let mut zv = unsafe { u8x4::from_slice_unaligned_unchecked(z) };
let xv = unsafe { u8x4::from_slice_unaligned_unchecked(x) };
zv += xv;
unsafe {
zv.write_to_slice_unaligned_unchecked(z);
zv.write_to_slice_unaligned_unchecked(x);
}
}
for i in (pixel_size..size.0 * pixel_size).step_by(4) {
let a = unsafe {
u8x4::from_slice_unaligned_unchecked(
pixels.get_unchecked(i - pixel_size..i - pixel_size + 4),
)
};
let z = unsafe { old_pixels.get_unchecked_mut(i..i + 4) };
let x = unsafe { pixels.get_unchecked_mut(i..i + 4) };
let mut zv = unsafe { u8x4::from_slice_unaligned_unchecked(z) };
let xv = unsafe { u8x4::from_slice_unaligned_unchecked(x) };
zv += xv;
unsafe {
zv.write_to_slice_unaligned_unchecked(z);
(zv + a).write_to_slice_unaligned_unchecked(x);
}
}
for i in (size.0 * pixel_size..pixels.len()).step_by(4) {
let a = i16x4::from(unsafe {
u8x4::from_slice_unaligned_unchecked(
pixels.get_unchecked(i - pixel_size..i - pixel_size + 4),
)
});
let b = i16x4::from(unsafe {
u8x4::from_slice_unaligned_unchecked(
pixels.get_unchecked(i - size.0 * pixel_size..i - size.0 * pixel_size + 4),
)
});
let c =
i16x4::from(unsafe {
u8x4::from_slice_unaligned_unchecked(pixels.get_unchecked(
i - (size.0 - 1) * pixel_size..i - (size.0 - 1) * pixel_size + 4,
))
});
let mut pa = b - c;
let mut pb = a - c;
let mut pc = pa + pb;
pa = abs(pa);
pb = abs(pb);
pc = abs(pc);
let smallest = pa.min(pb).min(pc);
let nearest = u8x4::from_cast(if_then_else(
i16x4::from_cast(smallest.eq(pa)),
a,
if_then_else(i16x4::from_cast(smallest.eq(pb)), b, c),
));
let z = unsafe { old_pixels.get_unchecked_mut(i..i + 4) };
let x = unsafe { pixels.get_unchecked_mut(i..i + 4) };
let mut zv = unsafe { u8x4::from_slice_unaligned_unchecked(z) };
let xv = unsafe { u8x4::from_slice_unaligned_unchecked(x) };
zv += xv;
unsafe {
zv.write_to_slice_unaligned_unchecked(z);
(zv + nearest).write_to_slice_unaligned_unchecked(x);
}
}
}
#[cfg(feature = "simd")]
#[allow(clippy::many_single_char_names)]
pub fn unfilter_simd_3(
size: (usize, usize),
pixel_size: usize,
pixels: &mut [u8],
old_pixels: &mut [u8],
) {
assert!(size.0 < u32::MAX as usize);
assert!(size.1 < u32::MAX as usize);
assert_eq!(pixel_size % 3, 0);
assert!(pixel_size < u8::MAX as usize);
assert_eq!(pixels.len(), size.0 * size.1 * pixel_size);
assert_eq!(pixels.len(), old_pixels.len());
if !pixels.is_empty() {
let z = unsafe { old_pixels.get_unchecked_mut(0..4) };
let x = unsafe { pixels.get_unchecked_mut(0..4) };
let mut zv = unsafe { u8x4::from_slice_unaligned_unchecked(z) };
let xv = unsafe { u8x4::from_slice_unaligned_unchecked(x) };
zv += xv;
z[0] = unsafe { zv.extract_unchecked(0) };
z[1] = unsafe { zv.extract_unchecked(1) };
z[2] = unsafe { zv.extract_unchecked(2) };
x[0] = unsafe { zv.extract_unchecked(0) };
x[1] = unsafe { zv.extract_unchecked(1) };
x[2] = unsafe { zv.extract_unchecked(2) };
}
for i in (pixel_size..size.0 * pixel_size).step_by(3) {
let a = unsafe {
u8x4::from_slice_unaligned_unchecked(
pixels.get_unchecked(i - pixel_size..i - pixel_size + 4),
)
};
let z = unsafe { old_pixels.get_unchecked_mut(i..i + 4) };
let x = unsafe { pixels.get_unchecked_mut(i..i + 4) };
let mut zv = unsafe { u8x4::from_slice_unaligned_unchecked(z) };
let xv = unsafe { u8x4::from_slice_unaligned_unchecked(x) };
zv += xv;
z[0] = unsafe { zv.extract_unchecked(0) };
z[1] = unsafe { zv.extract_unchecked(1) };
z[2] = unsafe { zv.extract_unchecked(2) };
zv += a;
x[0] = unsafe { zv.extract_unchecked(0) };
x[1] = unsafe { zv.extract_unchecked(1) };
x[2] = unsafe { zv.extract_unchecked(2) };
}
for i in (size.0 * pixel_size..pixels.len()).step_by(3) {
let a = i16x4::from(unsafe {
u8x4::from_slice_unaligned_unchecked(
pixels.get_unchecked(i - pixel_size..i - pixel_size + 4),
)
});
let b = i16x4::from(unsafe {
u8x4::from_slice_unaligned_unchecked(
pixels.get_unchecked(i - size.0 * pixel_size..i - size.0 * pixel_size + 4),
)
});
let c =
i16x4::from(unsafe {
u8x4::from_slice_unaligned_unchecked(pixels.get_unchecked(
i - (size.0 - 1) * pixel_size..i - (size.0 - 1) * pixel_size + 4,
))
});
let mut pa = b - c;
let mut pb = a - c;
let mut pc = pa + pb;
pa = abs(pa);
pb = abs(pb);
pc = abs(pc);
let smallest = pa.min(pb).min(pc);
let nearest = u8x4::from_cast(if_then_else(
i16x4::from_cast(smallest.eq(pa)),
a,
if_then_else(i16x4::from_cast(smallest.eq(pb)), b, c),
));
let z = unsafe { old_pixels.get_unchecked_mut(i..i + 4) };
let x = unsafe { pixels.get_unchecked_mut(i..i + 4) };
let mut zv = unsafe { u8x4::from_slice_unaligned_unchecked(z) };
let xv = unsafe { u8x4::from_slice_unaligned_unchecked(x) };
zv += xv;
z[0] = unsafe { zv.extract_unchecked(0) };
z[1] = unsafe { zv.extract_unchecked(1) };
z[2] = unsafe { zv.extract_unchecked(2) };
zv += nearest;
x[0] = unsafe { zv.extract_unchecked(0) };
x[1] = unsafe { zv.extract_unchecked(1) };
x[2] = unsafe { zv.extract_unchecked(2) };
}
}
#[cfg(test)]
mod test {
use super::*;
use rand::{
distributions::{Distribution, Uniform},
Fill,
};
pub fn valloc<T>(n: usize) -> Vec<T> {
let mut v = Vec::with_capacity(n);
unsafe {
v.set_len(n);
}
v
}
#[test]
fn test_filter_reversibility() {
let maxpixels = 100;
let mut pixels = valloc(maxpixels * maxpixels * 4);
let mut pixels_save = valloc(maxpixels * maxpixels * 4);
let mut old_pixels_enc = valloc(maxpixels * maxpixels * 4);
let mut old_pixels_dec = valloc(maxpixels * maxpixels * 4);
let size_range = Uniform::new(2, maxpixels);
let pixel_size_range = Uniform::new(1, 5);
let mut rng = rand::thread_rng();
for _ in 0..100 {
let size = (size_range.sample(&mut rng), size_range.sample(&mut rng));
let pixel_size = pixel_size_range.sample(&mut rng);
let len = size.0 * size.1 * pixel_size;
old_pixels_enc[..len].fill(0);
old_pixels_dec[..len].fill(0);
for _ in 0..10 {
pixels[..len].try_fill(&mut rng).unwrap();
pixels_save[..len].copy_from_slice(&pixels[..len]);
filter(
size,
pixel_size,
&mut pixels[..len],
&mut old_pixels_enc[..len],
);
unfilter(
size,
pixel_size,
&mut pixels[..len],
&mut old_pixels_dec[..len],
);
assert_eq!(&pixels[..len], &pixels_save[..len]);
}
}
}
#[test]
fn test_filter_same_image() {
let maxpixels = 100;
let mut pixels = valloc(maxpixels * maxpixels * 4);
let mut pixels_save = valloc(maxpixels * maxpixels * 4);
let mut old_pixels = valloc(maxpixels * maxpixels * 4);
let size_range = Uniform::new(2, maxpixels);
let pixel_size_range = Uniform::new(1, 5);
let mut rng = rand::thread_rng();
for _ in 0..10 {
let size = (size_range.sample(&mut rng), size_range.sample(&mut rng));
let pixel_size = pixel_size_range.sample(&mut rng);
let len = size.0 * size.1 * pixel_size;
pixels[..len].try_fill(&mut rng).unwrap();
pixels_save[..len].copy_from_slice(&pixels[..len]);
old_pixels[..len].try_fill(&mut rng).unwrap();
filter(size, pixel_size, &mut pixels[..len], &mut old_pixels[..len]);
filter(
size,
pixel_size,
&mut pixels_save[..len],
&mut old_pixels[..len],
);
pixels_save[pixel_size..len]
.iter()
.for_each(|&o| assert_eq!(o, 0));
}
}
#[cfg(feature = "simd")]
#[test]
fn test_filter_simd_4() {
let maxpixels = 10;
let mut pixels_sisd = valloc(maxpixels * maxpixels * 4);
let mut pixels_simd = valloc(maxpixels * maxpixels * 4);
let mut old_pixels_sisd = valloc(maxpixels * maxpixels * 4);
let mut old_pixels_simd = valloc(maxpixels * maxpixels * 4);
let size_range = Uniform::new(2, maxpixels);
let mut rng = rand::thread_rng();
for _ in 0..100 {
let size = (size_range.sample(&mut rng), size_range.sample(&mut rng));
let pixel_size = 4;
let len = size.0 * size.1 * pixel_size;
pixels_sisd[..len].try_fill(&mut rng).unwrap();
pixels_simd[..len].copy_from_slice(&pixels_sisd[..len]);
old_pixels_sisd[..len].try_fill(&mut rng).unwrap();
old_pixels_simd[..len].copy_from_slice(&old_pixels_sisd[..len]);
filter(
size,
pixel_size,
&mut pixels_sisd[..len],
&mut old_pixels_sisd[..len],
);
filter_simd_4(
size,
pixel_size,
&mut pixels_simd[..len],
&mut old_pixels_simd[..len],
);
assert_eq!(&pixels_sisd[..len], &pixels_simd[..len]);
assert_eq!(&old_pixels_sisd[..len], &old_pixels_simd[..len]);
}
for _ in 0..100 {
let size = (size_range.sample(&mut rng), size_range.sample(&mut rng));
let pixel_size = 4;
let len = size.0 * size.1 * pixel_size;
pixels_sisd[..len].try_fill(&mut rng).unwrap();
pixels_simd[..len].copy_from_slice(&pixels_sisd[..len]);
old_pixels_sisd[..len].try_fill(&mut rng).unwrap();
old_pixels_simd[..len].copy_from_slice(&old_pixels_sisd[..len]);
unfilter(
size,
pixel_size,
&mut pixels_sisd[..len],
&mut old_pixels_sisd[..len],
);
unfilter_simd_4(
size,
pixel_size,
&mut pixels_simd[..len],
&mut old_pixels_simd[..len],
);
assert_eq!(&pixels_sisd[..len], &pixels_simd[..len]);
assert_eq!(&old_pixels_sisd[..len], &old_pixels_simd[..len]);
}
}
#[cfg(feature = "simd")]
#[test]
fn test_filter_simd_3() {
let maxpixels = 10;
let mut pixels_sisd = valloc(maxpixels * maxpixels * 3);
let mut pixels_simd = valloc(maxpixels * maxpixels * 3);
let mut old_pixels_sisd = valloc(maxpixels * maxpixels * 3);
let mut old_pixels_simd = valloc(maxpixels * maxpixels * 3);
let size_range = Uniform::new(2, maxpixels);
let mut rng = rand::thread_rng();
for _ in 0..100 {
let size = (size_range.sample(&mut rng), size_range.sample(&mut rng));
let pixel_size = 3;
let len = size.0 * size.1 * pixel_size;
pixels_sisd[..len].try_fill(&mut rng).unwrap();
pixels_simd[..len].copy_from_slice(&pixels_sisd[..len]);
old_pixels_sisd[..len].try_fill(&mut rng).unwrap();
old_pixels_simd[..len].copy_from_slice(&old_pixels_sisd[..len]);
filter(
size,
pixel_size,
&mut pixels_sisd[..len],
&mut old_pixels_sisd[..len],
);
filter_simd_3(
size,
pixel_size,
&mut pixels_simd[..len],
&mut old_pixels_simd[..len],
);
assert_eq!(&pixels_sisd[..len], &pixels_simd[..len]);
assert_eq!(&old_pixels_sisd[..len], &old_pixels_simd[..len]);
}
for _ in 0..100 {
let size = (size_range.sample(&mut rng), size_range.sample(&mut rng));
let pixel_size = 3;
let len = size.0 * size.1 * pixel_size;
pixels_sisd[..len].try_fill(&mut rng).unwrap();
pixels_simd[..len].copy_from_slice(&pixels_sisd[..len]);
old_pixels_sisd[..len].try_fill(&mut rng).unwrap();
old_pixels_simd[..len].copy_from_slice(&old_pixels_sisd[..len]);
unfilter(
size,
pixel_size,
&mut pixels_sisd[..len],
&mut old_pixels_sisd[..len],
);
unfilter_simd_3(
size,
pixel_size,
&mut pixels_simd[..len],
&mut old_pixels_simd[..len],
);
assert_eq!(&pixels_sisd[..len], &pixels_simd[..len]);
assert_eq!(&old_pixels_sisd[..len], &old_pixels_simd[..len]);
}
}
}