use archmage::prelude::*;
const ALPHA_MASK_RGBA8: [u8; 32] = {
let mut a = [0u8; 32];
let mut i = 3;
while i < 32 {
a[i] = 0xFF;
i += 4;
}
a
};
const RGB_DELTA_MASK_RGBA8: [u8; 32] = {
let mut a = [0u8; 32];
let mut i = 0;
while i < 32 {
a[i] = 0xFF;
a[i + 1] = 0xFF;
i += 4;
}
a
};
const fn rgb8_phase_mask(start_phase: usize) -> [u8; 32] {
let mut a = [0u8; 32];
let mut k = 0;
while k < 32 {
let phase = (start_phase + k) % 3;
if phase == 0 || phase == 1 {
a[k] = 0xFF;
}
k += 1;
}
a
}
#[cfg(test)]
pub fn is_opaque_rgba8(rgba: &[u8]) -> bool {
incant!(is_opaque_rgba8_impl(rgba), [v3, neon, wasm128, scalar])
}
#[cfg(test)]
#[magetypes(define(u8x32), v3, neon, wasm128, scalar)]
fn is_opaque_rgba8_impl(token: Token, rgba: &[u8]) -> bool {
let alpha_mask = u8x32::from_array(token, ALPHA_MASK_RGBA8);
let opaque = u8x32::splat(token, 0xFF);
let (chunks, tail) = u8x32::partition_slice(token, rgba);
for chunk in chunks {
let v = u8x32::load(token, chunk);
let bad = v.simd_ne(opaque) & alpha_mask;
if bad.any_true() {
return false;
}
}
for px in tail.chunks_exact(4) {
if px[3] != 255 {
return false;
}
}
true
}
#[cfg(test)]
pub fn is_grayscale_rgba8(rgba: &[u8]) -> bool {
incant!(is_grayscale_rgba8_impl(rgba), [v3, neon, wasm128, scalar])
}
#[cfg(test)]
#[magetypes(define(u8x32), v3, neon, wasm128, scalar)]
fn is_grayscale_rgba8_impl(token: Token, rgba: &[u8]) -> bool {
let mask = u8x32::from_array(token, RGB_DELTA_MASK_RGBA8);
let mut i = 0;
while i + 33 <= rgba.len() {
let chunk0: &[u8; 32] = (&rgba[i..i + 32]).try_into().unwrap();
let chunk1: &[u8; 32] = (&rgba[i + 1..i + 33]).try_into().unwrap();
let v0 = u8x32::load(token, chunk0);
let v1 = u8x32::load(token, chunk1);
let masked = v0.simd_ne(v1) & mask;
if masked.any_true() {
return false;
}
i += 32;
}
for px in rgba[i..].chunks_exact(4) {
if px[0] != px[1] || px[1] != px[2] {
return false;
}
}
true
}
pub fn is_grayscale_rgb8(rgb: &[u8]) -> bool {
incant!(is_grayscale_rgb8_impl(rgb), [v3, neon, wasm128, scalar])
}
#[magetypes(define(u8x32), v3, neon, wasm128, scalar)]
fn is_grayscale_rgb8_impl(token: Token, rgb: &[u8]) -> bool {
let m0 = u8x32::from_array(token, rgb8_phase_mask(0));
let m1 = u8x32::from_array(token, rgb8_phase_mask(2));
let m2 = u8x32::from_array(token, rgb8_phase_mask(1));
let mut i = 0;
while i + 97 <= rgb.len() {
for (off, mask) in [(0usize, m0), (32, m1), (64, m2)] {
let c0: &[u8; 32] = (&rgb[i + off..i + off + 32]).try_into().unwrap();
let c1: &[u8; 32] = (&rgb[i + off + 1..i + off + 33]).try_into().unwrap();
let v0 = u8x32::load(token, c0);
let v1 = u8x32::load(token, c1);
let masked = v0.simd_ne(v1) & mask;
if masked.any_true() {
return false;
}
}
i += 96;
}
for px in rgb[i..].chunks_exact(3) {
if px[0] != px[1] || px[1] != px[2] {
return false;
}
}
true
}
pub fn bit_replication_lossless_u16(samples: &[u16]) -> bool {
incant!(
bit_replication_lossless_u16_impl(samples),
[v3, neon, wasm128, scalar]
)
}
#[magetypes(define(u16x16), v3, neon, wasm128, scalar)]
fn bit_replication_lossless_u16_impl(token: Token, samples: &[u16]) -> bool {
let lo_mask = u16x16::splat(token, 0xFF);
let (chunks, tail) = u16x16::partition_slice(token, samples);
for chunk in chunks {
let v = u16x16::load(token, chunk);
let hi = v.shr_logical_const::<8>();
let lo = v & lo_mask;
if hi.simd_ne(lo).any_true() {
return false;
}
}
for &s in tail {
if (s >> 8) as u8 != (s & 0xFF) as u8 {
return false;
}
}
true
}
const ALPHA_MASK_RGBA16: [u16; 16] = {
let mut a = [0u16; 16];
let mut i = 3;
while i < 16 {
a[i] = 0xFFFF;
i += 4;
}
a
};
const RGB_DELTA_MASK_RGBA16: [u16; 16] = {
let mut a = [0u16; 16];
let mut i = 0;
while i < 16 {
a[i] = 0xFFFF;
a[i + 1] = 0xFFFF;
i += 4;
}
a
};
const ALPHA_MASK_GA16: [u16; 16] = {
let mut a = [0u16; 16];
let mut i = 1;
while i < 16 {
a[i] = 0xFFFF;
i += 2;
}
a
};
const fn rgb16_phase_mask(start_phase: usize) -> [u16; 16] {
let mut a = [0u16; 16];
let mut k = 0;
while k < 16 {
let phase = (start_phase + k) % 3;
if phase == 0 || phase == 1 {
a[k] = 0xFFFF;
}
k += 1;
}
a
}
pub fn is_opaque_rgba16(rgba: &[u16]) -> bool {
incant!(is_opaque_rgba16_impl(rgba), [v3, neon, wasm128, scalar])
}
#[magetypes(define(u16x16), v3, neon, wasm128, scalar)]
fn is_opaque_rgba16_impl(token: Token, rgba: &[u16]) -> bool {
let alpha_mask = u16x16::from_array(token, ALPHA_MASK_RGBA16);
let opaque = u16x16::splat(token, 0xFFFF);
let (chunks, tail) = u16x16::partition_slice(token, rgba);
for chunk in chunks {
let v = u16x16::load(token, chunk);
let bad = v.simd_ne(opaque) & alpha_mask;
if bad.any_true() {
return false;
}
}
for px in tail.chunks_exact(4) {
if px[3] != 0xFFFF {
return false;
}
}
true
}
pub fn is_grayscale_rgba16(rgba: &[u16]) -> bool {
incant!(is_grayscale_rgba16_impl(rgba), [v3, neon, wasm128, scalar])
}
#[magetypes(define(u16x16), v3, neon, wasm128, scalar)]
fn is_grayscale_rgba16_impl(token: Token, rgba: &[u16]) -> bool {
let mask = u16x16::from_array(token, RGB_DELTA_MASK_RGBA16);
let mut i = 0;
while i + 17 <= rgba.len() {
let c0: &[u16; 16] = (&rgba[i..i + 16]).try_into().unwrap();
let c1: &[u16; 16] = (&rgba[i + 1..i + 17]).try_into().unwrap();
let v0 = u16x16::load(token, c0);
let v1 = u16x16::load(token, c1);
let masked = v0.simd_ne(v1) & mask;
if masked.any_true() {
return false;
}
i += 16;
}
for px in rgba[i..].chunks_exact(4) {
if px[0] != px[1] || px[1] != px[2] {
return false;
}
}
true
}
pub fn is_grayscale_rgb16(rgb: &[u16]) -> bool {
incant!(is_grayscale_rgb16_impl(rgb), [v3, neon, wasm128, scalar])
}
#[magetypes(define(u16x16), v3, neon, wasm128, scalar)]
fn is_grayscale_rgb16_impl(token: Token, rgb: &[u16]) -> bool {
let m0 = u16x16::from_array(token, rgb16_phase_mask(0));
let m1 = u16x16::from_array(token, rgb16_phase_mask(1));
let m2 = u16x16::from_array(token, rgb16_phase_mask(2));
let mut i = 0;
while i + 49 <= rgb.len() {
for (off, mask) in [(0usize, m0), (16, m1), (32, m2)] {
let c0: &[u16; 16] = (&rgb[i + off..i + off + 16]).try_into().unwrap();
let c1: &[u16; 16] = (&rgb[i + off + 1..i + off + 17]).try_into().unwrap();
let v0 = u16x16::load(token, c0);
let v1 = u16x16::load(token, c1);
let masked = v0.simd_ne(v1) & mask;
if masked.any_true() {
return false;
}
}
i += 48;
}
for px in rgb[i..].chunks_exact(3) {
if px[0] != px[1] || px[1] != px[2] {
return false;
}
}
true
}
const ALPHA_MASK_GA8: [u8; 32] = {
let mut a = [0u8; 32];
let mut i = 1;
while i < 32 {
a[i] = 0xFF;
i += 2;
}
a
};
pub fn is_opaque_ga8(ga: &[u8]) -> bool {
incant!(is_opaque_ga8_impl(ga), [v3, neon, wasm128, scalar])
}
#[magetypes(define(u8x32), v3, neon, wasm128, scalar)]
fn is_opaque_ga8_impl(token: Token, ga: &[u8]) -> bool {
let alpha_mask = u8x32::from_array(token, ALPHA_MASK_GA8);
let opaque = u8x32::splat(token, 0xFF);
let (chunks, tail) = u8x32::partition_slice(token, ga);
for chunk in chunks {
let v = u8x32::load(token, chunk);
let bad = v.simd_ne(opaque) & alpha_mask;
if bad.any_true() {
return false;
}
}
for px in tail.chunks_exact(2) {
if px[1] != 255 {
return false;
}
}
true
}
pub fn is_opaque_ga16(ga: &[u16]) -> bool {
incant!(is_opaque_ga16_impl(ga), [v3, neon, wasm128, scalar])
}
#[magetypes(define(u16x16), v3, neon, wasm128, scalar)]
fn is_opaque_ga16_impl(token: Token, ga: &[u16]) -> bool {
let alpha_mask = u16x16::from_array(token, ALPHA_MASK_GA16);
let opaque = u16x16::splat(token, 0xFFFF);
let (chunks, tail) = u16x16::partition_slice(token, ga);
for chunk in chunks {
let v = u16x16::load(token, chunk);
let bad = v.simd_ne(opaque) & alpha_mask;
if bad.any_true() {
return false;
}
}
for px in tail.chunks_exact(2) {
if px[1] != 0xFFFF {
return false;
}
}
true
}
const ALPHA_MASK_RGBA_I32: [i32; 8] = {
let mut a = [0i32; 8];
let mut i = 3;
while i < 8 {
a[i] = -1;
i += 4;
}
a
};
const RGB_DELTA_MASK_RGBA_I32: [i32; 8] = {
let mut a = [0i32; 8];
let mut i = 0;
while i < 8 {
a[i] = -1;
a[i + 1] = -1;
i += 4;
}
a
};
const ALPHA_MASK_GA_I32: [i32; 8] = {
let mut a = [0i32; 8];
let mut i = 1;
while i < 8 {
a[i] = -1;
i += 2;
}
a
};
const fn rgb_phase_mask_i32(start_phase: usize) -> [i32; 8] {
let mut a = [0i32; 8];
let mut k = 0;
while k < 8 {
let phase = (start_phase + k) % 3;
if phase == 0 || phase == 1 {
a[k] = -1;
}
k += 1;
}
a
}
pub fn is_opaque_rgba_f32(rgba: &[f32]) -> bool {
incant!(is_opaque_rgba_f32_impl(rgba), [v3, neon, wasm128, scalar])
}
#[magetypes(define(f32x8, i32x8), v3, neon, wasm128, scalar)]
fn is_opaque_rgba_f32_impl(token: Token, rgba: &[f32]) -> bool {
let alpha_mask = i32x8::from_array(token, ALPHA_MASK_RGBA_I32);
let one = f32x8::splat(token, 1.0);
let (chunks, tail) = f32x8::partition_slice(token, rgba);
for chunk in chunks {
let v = f32x8::load(token, chunk);
let bad = v.simd_ne(one).bitcast_to_i32() & alpha_mask;
if bad.any_true() {
return false;
}
}
for px in tail.chunks_exact(4) {
if px[3] != 1.0 {
return false;
}
}
true
}
pub fn is_grayscale_rgba_f32(rgba: &[f32]) -> bool {
incant!(
is_grayscale_rgba_f32_impl(rgba),
[v3, neon, wasm128, scalar]
)
}
#[magetypes(define(f32x8, i32x8), v3, neon, wasm128, scalar)]
fn is_grayscale_rgba_f32_impl(token: Token, rgba: &[f32]) -> bool {
let mask = i32x8::from_array(token, RGB_DELTA_MASK_RGBA_I32);
let mut i = 0;
while i + 9 <= rgba.len() {
let c0: &[f32; 8] = (&rgba[i..i + 8]).try_into().unwrap();
let c1: &[f32; 8] = (&rgba[i + 1..i + 9]).try_into().unwrap();
let v0 = f32x8::load(token, c0);
let v1 = f32x8::load(token, c1);
let masked = v0.simd_ne(v1).bitcast_to_i32() & mask;
if masked.any_true() {
return false;
}
i += 8;
}
for px in rgba[i..].chunks_exact(4) {
if px[0] != px[1] || px[1] != px[2] {
return false;
}
}
true
}
pub fn is_grayscale_rgb_f32(rgb: &[f32]) -> bool {
incant!(is_grayscale_rgb_f32_impl(rgb), [v3, neon, wasm128, scalar])
}
#[magetypes(define(f32x8, i32x8), v3, neon, wasm128, scalar)]
fn is_grayscale_rgb_f32_impl(token: Token, rgb: &[f32]) -> bool {
let m0 = i32x8::from_array(token, rgb_phase_mask_i32(0));
let m1 = i32x8::from_array(token, rgb_phase_mask_i32(2));
let m2 = i32x8::from_array(token, rgb_phase_mask_i32(1));
let mut i = 0;
while i + 25 <= rgb.len() {
for (off, mask) in [(0usize, m0), (8, m1), (16, m2)] {
let c0: &[f32; 8] = (&rgb[i + off..i + off + 8]).try_into().unwrap();
let c1: &[f32; 8] = (&rgb[i + off + 1..i + off + 9]).try_into().unwrap();
let v0 = f32x8::load(token, c0);
let v1 = f32x8::load(token, c1);
let masked = v0.simd_ne(v1).bitcast_to_i32() & mask;
if masked.any_true() {
return false;
}
}
i += 24;
}
for px in rgb[i..].chunks_exact(3) {
if px[0] != px[1] || px[1] != px[2] {
return false;
}
}
true
}
pub fn is_opaque_ga_f32(ga: &[f32]) -> bool {
incant!(is_opaque_ga_f32_impl(ga), [v3, neon, wasm128, scalar])
}
#[magetypes(define(f32x8, i32x8), v3, neon, wasm128, scalar)]
fn is_opaque_ga_f32_impl(token: Token, ga: &[f32]) -> bool {
let alpha_mask = i32x8::from_array(token, ALPHA_MASK_GA_I32);
let one = f32x8::splat(token, 1.0);
let (chunks, tail) = f32x8::partition_slice(token, ga);
for chunk in chunks {
let v = f32x8::load(token, chunk);
let bad = v.simd_ne(one).bitcast_to_i32() & alpha_mask;
if bad.any_true() {
return false;
}
}
for px in tail.chunks_exact(2) {
if px[1] != 1.0 {
return false;
}
}
true
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct FusedRequest {
pub check_opaque: bool,
pub check_grayscale: bool,
}
impl FusedRequest {
#[cfg(test)]
pub const fn all() -> Self {
Self {
check_opaque: true,
check_grayscale: true,
}
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct FusedResult {
pub is_opaque: bool,
pub is_grayscale: bool,
}
#[cfg(test)]
pub fn fused_predicates_rgba8(rgba: &[u8], req: FusedRequest) -> FusedResult {
incant!(
fused_predicates_rgba8_impl(rgba, req),
[v3, neon, wasm128, scalar]
)
}
#[cfg(test)]
#[magetypes(define(u8x32), v3, neon, wasm128, scalar)]
fn fused_predicates_rgba8_impl(token: Token, rgba: &[u8], req: FusedRequest) -> FusedResult {
let alpha_mask = u8x32::from_array(token, ALPHA_MASK_RGBA8);
let rgb_delta_mask = u8x32::from_array(token, RGB_DELTA_MASK_RGBA8);
let opaque = u8x32::splat(token, 0xFF);
let mut still_o = req.check_opaque;
let mut still_g = req.check_grayscale;
let mut i = 0;
let len = rgba.len();
while still_o | still_g {
if !still_g && i + 32 > len {
break;
}
if still_g && i + 33 > len {
break;
}
let chunk0: &[u8; 32] = (&rgba[i..i + 32]).try_into().unwrap();
let v0 = u8x32::load(token, chunk0);
if still_o {
let bad = v0.simd_ne(opaque) & alpha_mask;
if bad.any_true() {
still_o = false;
}
}
if still_g {
let chunk1: &[u8; 32] = (&rgba[i + 1..i + 33]).try_into().unwrap();
let v1 = u8x32::load(token, chunk1);
let bad = v0.simd_ne(v1) & rgb_delta_mask;
if bad.any_true() {
still_g = false;
}
}
i += 32;
}
while i + 4 <= len && (still_o | still_g) {
let r = rgba[i];
let g = rgba[i + 1];
let b = rgba[i + 2];
let a = rgba[i + 3];
if still_o && a != 255 {
still_o = false;
}
if still_g && (r != g || g != b) {
still_g = false;
}
i += 4;
}
FusedResult {
is_opaque: still_o,
is_grayscale: still_g,
}
}
pub fn fused_predicates_rgba8_cg(rgba: &[u8], req: FusedRequest) -> FusedResult {
match (req.check_opaque, req.check_grayscale) {
(true, true) => fused_cg::<true, true>(rgba),
(true, false) => fused_cg::<true, false>(rgba),
(false, true) => fused_cg::<false, true>(rgba),
(false, false) => FusedResult::default(),
}
}
#[inline]
fn fused_cg<const A: bool, const B: bool>(rgba: &[u8]) -> FusedResult {
incant!(fused_cg_impl::<A, B>(rgba), [v3, neon, wasm128, scalar])
}
fn fused_cg_resume(rest: &[u8], next_a: bool, next_b: bool) -> FusedResult {
match (next_a, next_b) {
(true, true) => unreachable!("resume only runs after a flip"),
(true, false) => {
let s = fused_cg::<true, false>(rest);
FusedResult {
is_opaque: s.is_opaque,
is_grayscale: false,
}
}
(false, true) => {
let s = fused_cg::<false, true>(rest);
FusedResult {
is_opaque: false,
is_grayscale: s.is_grayscale,
}
}
(false, false) => FusedResult::default(),
}
}
#[magetypes(define(u8x32), v3, neon, wasm128, scalar)]
fn fused_cg_impl<const A: bool, const B: bool>(token: Token, rgba: &[u8]) -> FusedResult {
if !(A || B) {
return FusedResult::default();
}
let alpha_mask = u8x32::from_array(token, ALPHA_MASK_RGBA8);
let rgb_delta_mask = u8x32::from_array(token, RGB_DELTA_MASK_RGBA8);
let opaque = u8x32::splat(token, 0xFF);
let len = rgba.len();
let mut i = 0;
const BLOCK_BYTES: usize = 16 * 32;
let chunkable = (if B { len.saturating_sub(1) } else { len }) / 32 * 32;
while i < chunkable {
let block_end = (i + BLOCK_BYTES).min(chunkable);
let mut acc = u8x32::splat(token, 0);
let mut j = i;
while j < block_end {
let chunk0: &[u8; 32] = (&rgba[j..j + 32]).try_into().unwrap();
let v0 = u8x32::load(token, chunk0);
if A {
acc |= v0.simd_ne(opaque) & alpha_mask;
}
if B {
let chunk1: &[u8; 32] = (&rgba[j + 1..j + 33]).try_into().unwrap();
let v1 = u8x32::load(token, chunk1);
acc |= v0.simd_ne(v1) & rgb_delta_mask;
}
j += 32;
}
if acc.any_true() {
let mut next_a = A;
let mut next_b = B;
for px in rgba[i..block_end].chunks_exact(4) {
if A && px[3] != 255 {
next_a = false;
}
if B && (px[0] != px[1] || px[1] != px[2]) {
next_b = false;
}
}
debug_assert!(
(next_a, next_b) != (A, B),
"accumulator fired but the re-scan found no flip"
);
return fused_cg_resume(&rgba[block_end..], next_a, next_b);
}
i = block_end;
}
let mut o = A;
let mut g = B;
while i + 4 <= len && (o | g) {
let r = rgba[i];
let gg = rgba[i + 1];
let bb = rgba[i + 2];
let a = rgba[i + 3];
if A && o && a != 255 {
o = false;
}
if B && g && (r != gg || gg != bb) {
g = false;
}
i += 4;
}
FusedResult {
is_opaque: o,
is_grayscale: g,
}
}
#[cfg(test)]
mod tests {
use archmage::testing::{CompileTimePolicy, for_each_token_permutation};
fn scalar_is_opaque(rgba: &[u8]) -> bool {
rgba.chunks_exact(4).all(|p| p[3] == 255)
}
fn scalar_is_grayscale_rgba8(rgba: &[u8]) -> bool {
rgba.chunks_exact(4).all(|p| p[0] == p[1] && p[1] == p[2])
}
fn scalar_is_grayscale_rgb8(rgb: &[u8]) -> bool {
rgb.chunks_exact(3).all(|p| p[0] == p[1] && p[1] == p[2])
}
fn scalar_bit_replication_u16(samples: &[u16]) -> bool {
samples.iter().all(|&s| (s >> 8) == (s & 0xFF))
}
fn run_at_all_tiers(label: &str, body: impl Fn()) {
let report = for_each_token_permutation(CompileTimePolicy::Warn, |_perm| body());
eprintln!("{label}: {report}");
}
#[test]
fn is_opaque_true_one_pixel() {
run_at_all_tiers("opaque_true_1px", || {
assert!(super::is_opaque_rgba8(&[100, 50, 25, 255]));
});
}
#[test]
fn is_opaque_true_four_pixels() {
run_at_all_tiers("opaque_true_4px", || {
assert!(super::is_opaque_rgba8(&[
10, 20, 30, 255, 40, 50, 60, 255, 70, 80, 90, 255, 100, 110, 120, 255,
]));
});
}
#[test]
fn is_opaque_false_alpha_zero_at_first() {
run_at_all_tiers("opaque_false_first_alpha_0", || {
assert!(!super::is_opaque_rgba8(&[
10, 20, 30, 0, 40, 50, 60, 255,
]));
});
}
#[test]
fn is_opaque_false_alpha_254_at_last() {
run_at_all_tiers("opaque_false_last_alpha_254", || {
assert!(!super::is_opaque_rgba8(&[
10, 20, 30, 255, 40, 50, 60, 254,
]));
});
}
#[test]
fn is_opaque_false_alpha_128_in_middle_of_simd_chunk() {
run_at_all_tiers("opaque_false_alpha_128_pixel_5", || {
let mut v = [0u8; 64];
for i in 0..16 {
v[i * 4] = (i * 7) as u8;
v[i * 4 + 1] = (i * 7) as u8;
v[i * 4 + 2] = (i * 7) as u8;
v[i * 4 + 3] = 255;
}
v[5 * 4 + 3] = 128;
assert!(!super::is_opaque_rgba8(&v));
});
}
#[test]
fn is_opaque_empty_buffer_is_true() {
run_at_all_tiers("opaque_empty", || {
assert!(super::is_opaque_rgba8(&[]));
});
}
#[test]
fn grayscale_rgba8_true_one_pixel() {
run_at_all_tiers("gray_rgba_true_1px", || {
assert!(super::is_grayscale_rgba8(&[128, 128, 128, 255]));
});
}
#[test]
fn grayscale_rgba8_true_with_varying_alpha() {
run_at_all_tiers("gray_rgba_true_var_alpha", || {
assert!(super::is_grayscale_rgba8(&[
42, 42, 42, 255, 42, 42, 42, 0, 42, 42, 42, 64,
]));
});
}
#[test]
fn grayscale_rgba8_false_first_pixel_g_differs() {
run_at_all_tiers("gray_rgba_false_first_g", || {
assert!(!super::is_grayscale_rgba8(&[10, 11, 10, 255]));
});
}
#[test]
fn grayscale_rgba8_false_last_pixel_b_differs() {
run_at_all_tiers("gray_rgba_false_last_b", || {
assert!(!super::is_grayscale_rgba8(&[
10, 10, 10, 255, 20, 20, 21, 255,
]));
});
}
#[test]
fn grayscale_rgba8_false_off_by_one_in_simd_chunk() {
run_at_all_tiers("gray_rgba_false_off_by_one", || {
let mut v = [0u8; 68];
for i in 0..17 {
let g = (i * 13) as u8;
v[i * 4] = g;
v[i * 4 + 1] = g;
v[i * 4 + 2] = g;
v[i * 4 + 3] = 255;
}
v[7 * 4 + 1] = v[7 * 4].wrapping_add(1); assert!(!super::is_grayscale_rgba8(&v));
});
}
#[test]
fn grayscale_rgb8_true_one_pixel() {
run_at_all_tiers("gray_rgb_true_1px", || {
assert!(super::is_grayscale_rgb8(&[42, 42, 42]));
});
}
#[test]
fn grayscale_rgb8_true_three_pixels() {
run_at_all_tiers("gray_rgb_true_3px", || {
assert!(super::is_grayscale_rgb8(&[
10, 10, 10, 20, 20, 20, 30, 30, 30
]));
});
}
#[test]
fn grayscale_rgb8_false_first_pixel() {
run_at_all_tiers("gray_rgb_false_first", || {
assert!(!super::is_grayscale_rgb8(&[10, 11, 10]));
});
}
#[test]
fn grayscale_rgb8_false_in_supernode_phase_1() {
run_at_all_tiers("gray_rgb_false_phase1", || {
let mut v = [0u8; 192];
for i in 0..64 {
let g = (i * 3) as u8;
v[i * 3] = g;
v[i * 3 + 1] = g;
v[i * 3 + 2] = g;
}
v[30 * 3 + 1] = v[30 * 3].wrapping_add(1);
assert!(!super::is_grayscale_rgb8(&v));
});
}
#[test]
fn grayscale_rgb8_false_in_phase_2() {
run_at_all_tiers("gray_rgb_false_phase2", || {
let mut v = [0u8; 192];
for i in 0..64 {
let g = (i * 3) as u8;
v[i * 3] = g;
v[i * 3 + 1] = g;
v[i * 3 + 2] = g;
}
v[50 * 3 + 2] = v[50 * 3].wrapping_add(7);
assert!(!super::is_grayscale_rgb8(&v));
});
}
#[test]
fn bit_repl_u16_true() {
run_at_all_tiers("repl_u16_true", || {
assert!(super::bit_replication_lossless_u16(&[
0xFEFE, 0x1212, 0x0000, 0xFFFF,
]));
});
}
#[test]
fn bit_repl_u16_false() {
run_at_all_tiers("repl_u16_false", || {
assert!(!super::bit_replication_lossless_u16(&[0xFE00]));
});
}
#[test]
fn bit_repl_u16_endian_agnostic() {
run_at_all_tiers("repl_u16_endian", || {
assert!(super::bit_replication_lossless_u16(&[0x1212]));
assert!(!super::bit_replication_lossless_u16(&[0x1200]));
assert!(!super::bit_replication_lossless_u16(&[0x0012]));
});
}
#[test]
fn bit_repl_u16_rejects_real_world_inexact_widenings() {
run_at_all_tiers("repl_u16_rejects_inexact", || {
let shifted: alloc::vec::Vec<u16> = (0..64u16).map(|v| (v * 4) << 8).collect();
assert!(!super::bit_replication_lossless_u16(&shifted));
let unscaled: alloc::vec::Vec<u16> = (1..65u16).map(|v| v * 3 % 256).collect();
assert!(!super::bit_replication_lossless_u16(&unscaled));
assert!(!super::bit_replication_lossless_u16(&[
0xC8FF, 0x7FFF, 0xFF03,
]));
});
}
#[test]
fn bit_repl_u16_false_in_simd_chunk() {
run_at_all_tiers("repl_u16_false_simd_chunk", || {
let mut v = [0u16; 32];
for (i, s) in v.iter_mut().enumerate() {
*s = (i as u16 * 17) % 256 * 0x0101;
}
v[17] ^= 0x0001; assert!(!super::bit_replication_lossless_u16(&v));
});
}
#[test]
fn rgba16_opaque_true() {
run_at_all_tiers("rgba16_opaque_true", || {
assert!(super::is_opaque_rgba16(&[
0x1234, 0x5678, 0x9ABC, 0xFFFF, 0x4321, 0x8765, 0xCBA9, 0xFFFF,
]));
});
}
#[test]
fn rgba16_opaque_false_alpha_lt_max() {
run_at_all_tiers("rgba16_opaque_false", || {
assert!(!super::is_opaque_rgba16(&[
0x1234, 0x5678, 0x9ABC, 0xFFFE, ]));
});
}
#[test]
fn rgba16_grayscale_true() {
run_at_all_tiers("rgba16_gray_true", || {
assert!(super::is_grayscale_rgba16(&[
0x4242, 0x4242, 0x4242, 0x8000, 0x9999, 0x9999, 0x9999, 0x0000,
]));
});
}
#[test]
fn rgba16_grayscale_false() {
run_at_all_tiers("rgba16_gray_false", || {
assert!(!super::is_grayscale_rgba16(&[
0x4242, 0x4243, 0x4242, 0x8000, ]));
});
}
#[test]
fn rgb16_grayscale_true() {
run_at_all_tiers("rgb16_gray_true", || {
assert!(super::is_grayscale_rgb16(&[
0x4242, 0x4242, 0x4242, 0x9999, 0x9999, 0x9999, 0x0000, 0x0000, 0x0000,
]));
});
}
#[test]
fn rgb16_grayscale_false() {
run_at_all_tiers("rgb16_gray_false", || {
assert!(!super::is_grayscale_rgb16(&[
0x4242, 0x4243, 0x4242, ]));
});
}
#[test]
fn rgb16_grayscale_false_in_simd_super_chunk() {
run_at_all_tiers("rgb16_gray_false_super", || {
let mut v = vec![0u16; 96];
for i in 0..32 {
let g = (i as u16) * 0x0202;
v[i * 3] = g;
v[i * 3 + 1] = g;
v[i * 3 + 2] = g;
}
v[20 * 3 + 1] = v[20 * 3].wrapping_add(1); assert!(!super::is_grayscale_rgb16(&v));
});
}
#[test]
fn ga8_opaque_true() {
run_at_all_tiers("ga8_opaque_true", || {
assert!(super::is_opaque_ga8(&[
100, 255, 50, 255, 200, 255,
]));
});
}
#[test]
fn ga8_opaque_false() {
run_at_all_tiers("ga8_opaque_false", || {
assert!(!super::is_opaque_ga8(&[100, 255, 50, 128, 200, 255]));
});
}
#[test]
fn ga16_opaque_true() {
run_at_all_tiers("ga16_opaque_true", || {
assert!(super::is_opaque_ga16(&[0x1234, 0xFFFF, 0x5678, 0xFFFF]));
});
}
#[test]
fn ga16_opaque_false() {
run_at_all_tiers("ga16_opaque_false", || {
assert!(!super::is_opaque_ga16(&[0x1234, 0xFFFE]));
});
}
#[test]
fn rgba_f32_opaque_true() {
run_at_all_tiers("rgba_f32_opaque_true", || {
assert!(super::is_opaque_rgba_f32(&[
0.1, 0.2, 0.3, 1.0, 0.4, 0.5, 0.6, 1.0,
]));
});
}
#[test]
fn rgba_f32_opaque_false_alpha_lt_one() {
run_at_all_tiers("rgba_f32_opaque_false", || {
assert!(!super::is_opaque_rgba_f32(&[
0.1, 0.2, 0.3, 0.999, ]));
});
}
#[test]
fn rgba_f32_opaque_false_in_simd_chunk() {
run_at_all_tiers("rgba_f32_opaque_simd_chunk", || {
let mut v = vec![0.5_f32; 32];
for i in 0..8 {
v[i * 4 + 3] = 1.0;
}
v[5 * 4 + 3] = 0.5; assert!(!super::is_opaque_rgba_f32(&v));
});
}
#[test]
fn rgba_f32_grayscale_true() {
run_at_all_tiers("rgba_f32_gray_true", || {
assert!(super::is_grayscale_rgba_f32(&[
0.42, 0.42, 0.42, 1.0, 0.99, 0.99, 0.99, 0.5, 0.0, 0.0, 0.0, 0.0,
]));
});
}
#[test]
fn rgba_f32_grayscale_false() {
run_at_all_tiers("rgba_f32_gray_false", || {
assert!(!super::is_grayscale_rgba_f32(&[0.42, 0.420001, 0.42, 1.0,]));
});
}
#[test]
fn rgba_f32_grayscale_false_in_simd_chunk() {
run_at_all_tiers("rgba_f32_gray_simd_chunk", || {
let mut v = vec![0.0_f32; 8 * 4];
for i in 0..8 {
let g = (i as f32) * 0.1;
v[i * 4] = g;
v[i * 4 + 1] = g;
v[i * 4 + 2] = g;
v[i * 4 + 3] = 1.0;
}
v[6 * 4 + 1] = v[6 * 4] + 0.001; assert!(!super::is_grayscale_rgba_f32(&v));
});
}
#[test]
fn rgb_f32_grayscale_true() {
run_at_all_tiers("rgb_f32_gray_true", || {
assert!(super::is_grayscale_rgb_f32(&[
0.42, 0.42, 0.42, 0.99, 0.99, 0.99, 0.0, 0.0, 0.0,
]));
});
}
#[test]
fn rgb_f32_grayscale_false() {
run_at_all_tiers("rgb_f32_gray_false", || {
assert!(!super::is_grayscale_rgb_f32(&[0.5, 0.5001, 0.5]));
});
}
#[test]
fn rgb_f32_grayscale_false_in_super_chunk() {
run_at_all_tiers("rgb_f32_gray_super_chunk", || {
let mut v = vec![0.0_f32; 16 * 3];
for i in 0..16 {
let g = (i as f32) * 0.05;
v[i * 3] = g;
v[i * 3 + 1] = g;
v[i * 3 + 2] = g;
}
v[10 * 3 + 1] = v[10 * 3] + 0.01;
assert!(!super::is_grayscale_rgb_f32(&v));
});
}
#[test]
fn ga_f32_opaque_true() {
run_at_all_tiers("ga_f32_opaque_true", || {
assert!(super::is_opaque_ga_f32(&[0.5, 1.0, 0.7, 1.0, 0.2, 1.0]));
});
}
#[test]
fn ga_f32_opaque_false() {
run_at_all_tiers("ga_f32_opaque_false", || {
assert!(!super::is_opaque_ga_f32(&[0.5, 1.0, 0.7, 0.5]));
});
}
fn scalar_fused(rgba: &[u8], req: super::FusedRequest) -> super::FusedResult {
let mut o = req.check_opaque;
let mut g = req.check_grayscale;
for chunk in rgba.chunks_exact(4) {
if o && chunk[3] != 255 {
o = false;
}
if g && (chunk[0] != chunk[1] || chunk[1] != chunk[2]) {
g = false;
}
}
super::FusedResult {
is_opaque: o,
is_grayscale: g,
}
}
fn run_fused_match_test(label: &str, rgba: &[u8], req: super::FusedRequest) {
let expected = scalar_fused(rgba, req);
run_at_all_tiers(&format!("fused_runtime_{label}"), || {
let got = super::fused_predicates_rgba8(rgba, req);
assert_eq!(
got, expected,
"runtime mismatch label={label} req={req:?} expected={expected:?}"
);
});
run_at_all_tiers(&format!("fused_cg_{label}"), || {
let got = super::fused_predicates_rgba8_cg(rgba, req);
assert_eq!(
got, expected,
"const-generic mismatch label={label} req={req:?} expected={expected:?}"
);
});
}
#[test]
fn fused_pure_grayscale_opaque() {
let v = [
10, 10, 10, 255, 20, 20, 20, 255, 30, 30, 30, 255,
];
run_fused_match_test("gray_opaque", &v, super::FusedRequest::all());
}
#[test]
fn fused_colorful_with_mixed_alpha() {
let v = [
10, 20, 30, 0, 40, 50, 60, 255, 70, 80, 90, 0,
];
run_fused_match_test("color_mixed_alpha", &v, super::FusedRequest::all());
}
#[test]
fn fused_first_pixel_breaks_all_three() {
let mut v = [255u8; 256]; v[0] = 0;
v[1] = 1;
v[2] = 2;
v[3] = 128;
run_fused_match_test("first_break_all", &v, super::FusedRequest::all());
}
#[test]
fn fused_subset_only_opaque() {
let v = [10, 20, 30, 255, 40, 50, 60, 255]; let req = super::FusedRequest {
check_opaque: true,
check_grayscale: false,
};
run_fused_match_test("subset_opaque_only", &v, req);
}
#[test]
fn fused_subset_only_grayscale_with_simd_chunk() {
let mut v = [0u8; 256];
for i in 0..64 {
let g = (i * 3) as u8;
v[i * 4] = g;
v[i * 4 + 1] = g;
v[i * 4 + 2] = g;
v[i * 4 + 3] = if i & 1 == 0 { 0 } else { 200 };
}
let req = super::FusedRequest {
check_opaque: false,
check_grayscale: true,
};
run_fused_match_test("subset_gray_only_64px", &v, req);
}
#[test]
fn fused_no_checks_requested() {
let v = [10, 20, 30, 128, 40, 50, 60, 255];
let req = super::FusedRequest::default();
run_fused_match_test("no_checks", &v, req);
}
#[test]
fn fused_grayscale_breaks_at_pixel_5_in_simd_chunk() {
let mut v = [0u8; 64];
for i in 0..16 {
let g = (i * 11) as u8;
v[i * 4] = g;
v[i * 4 + 1] = g;
v[i * 4 + 2] = g;
v[i * 4 + 3] = 255;
}
v[5 * 4 + 1] = v[5 * 4].wrapping_add(7); run_fused_match_test("gray_break_chunk", &v, super::FusedRequest::all());
}
#[test]
fn fused_opaque_breaks_at_simd_boundary() {
let mut v = [0u8; 128];
for i in 0..32 {
let g = (i * 5) as u8;
v[i * 4] = g;
v[i * 4 + 1] = g;
v[i * 4 + 2] = g;
v[i * 4 + 3] = 255;
}
v[20 * 4 + 3] = 64; run_fused_match_test("opaque_break_chunk2", &v, super::FusedRequest::all());
}
#[test]
fn fused_all_three_break_at_different_pixels() {
let mut v = [0u8; 64];
for i in 0..16 {
let g = (i * 3) as u8;
v[i * 4] = g;
v[i * 4 + 1] = g;
v[i * 4 + 2] = g;
v[i * 4 + 3] = if i & 1 == 0 { 0 } else { 255 };
}
v[3 * 4 + 3] = 128; v[7 * 4 + 1] = v[7 * 4].wrapping_add(1);
run_fused_match_test("multi_break", &v, super::FusedRequest::all());
}
#[test]
fn fused_short_buffer_only_scalar_tail() {
let v = [
10, 10, 10, 255, 20, 20, 20, 0, 30, 30, 30, 255, 40, 41, 40, 0, 50, 50, 50, 255, 60, 60, 60, 200, 70, 70, 70, 0, 80, 80, 80, 255,
];
run_fused_match_test("short_tail_only", &v, super::FusedRequest::all());
}
#[test]
fn fused_breaks_around_block_boundaries() {
let n = 3 * 128 + 16 + 1;
for &break_px in &[
0usize, 126, 127, 128, 129, 255, 256, 257, 383, 384, 399, 400,
] {
let mut v = rgba_pattern(n, |_, _| {});
v[break_px * 4 + 3] = 128;
run_fused_match_test(
&format!("blk_opaque_at_{break_px}"),
&v,
super::FusedRequest::all(),
);
let mut v = rgba_pattern(n, |_, _| {});
v[break_px * 4 + 1] = v[break_px * 4].wrapping_add(1);
run_fused_match_test(
&format!("blk_gray_at_{break_px}"),
&v,
super::FusedRequest::all(),
);
}
}
#[test]
fn fused_flips_land_in_different_blocks() {
let n = 3 * 128 + 7;
let mut v = rgba_pattern(n, |_, _| {});
v[10 * 4 + 2] = v[10 * 4].wrapping_add(3);
v[300 * 4 + 3] = 77;
run_fused_match_test("blk_gray_b0_alpha_b2", &v, super::FusedRequest::all());
}
#[test]
fn fused_flip_in_block_then_scalar_tail() {
let n = 128 + 3; let mut v = rgba_pattern(n, |_, _| {});
v[5 * 4 + 3] = 9; v[(n - 1) * 4 + 1] = v[(n - 1) * 4].wrapping_add(1); run_fused_match_test("blk_alpha_b0_gray_tail", &v, super::FusedRequest::all());
}
#[test]
fn fused_runtime_and_cg_agree_on_random_inputs() {
let mut state: u32 = 0xC0FFEE12;
let mut next = || {
state = state.wrapping_mul(1664525).wrapping_add(1013904223);
state
};
for trial in 0..10 {
let n_pixels = 100 + (next() % 4096) as usize;
let mut v = Vec::with_capacity(n_pixels * 4);
for _ in 0..n_pixels {
let r = next() as u8;
let g_chance = (next() % 4 == 0) as u8;
let g = if g_chance == 0 { r } else { next() as u8 };
let b = if g_chance == 0 { r } else { next() as u8 };
let a = match next() % 5 {
0 => 0,
1 => 255,
2 => 128,
_ => next() as u8,
};
v.extend_from_slice(&[r, g, b, a]);
}
let req = super::FusedRequest::all();
let runtime = super::fused_predicates_rgba8(&v, req);
let cg = super::fused_predicates_rgba8_cg(&v, req);
let scalar = scalar_fused(&v, req);
assert_eq!(
runtime, scalar,
"trial {trial}: runtime != scalar n_pixels={n_pixels}"
);
assert_eq!(
cg, scalar,
"trial {trial}: cg != scalar n_pixels={n_pixels}"
);
}
}
fn rgba_pattern(n_pixels: usize, mutate: impl Fn(usize, &mut [u8; 4])) -> Vec<u8> {
let mut v = Vec::with_capacity(n_pixels * 4);
for i in 0..n_pixels {
let mut p = [(i * 7 + 3) as u8, (i * 7 + 3) as u8, (i * 7 + 3) as u8, 255];
mutate(i, &mut p);
v.extend_from_slice(&p);
}
v
}
#[test]
fn opaque_predicate_matches_scalar_all_tiers() {
let report = for_each_token_permutation(CompileTimePolicy::Warn, |_perm| {
for &n in &[0usize, 1, 4, 15, 16, 17, 31, 64, 200, 1024, 4099] {
let v = rgba_pattern(n, |_, _| {});
assert_eq!(
super::is_opaque_rgba8(&v),
scalar_is_opaque(&v),
"n={n} all-opaque"
);
if n > 5 {
let mut v = rgba_pattern(n, |_, _| {});
v[5 * 4 + 3] = 128;
assert_eq!(
super::is_opaque_rgba8(&v),
scalar_is_opaque(&v),
"n={n} pixel 5 alpha=128"
);
}
if n > 0 {
let mut v = rgba_pattern(n, |_, _| {});
v[(n - 1) * 4 + 3] = 200;
assert_eq!(
super::is_opaque_rgba8(&v),
scalar_is_opaque(&v),
"n={n} last pixel alpha=200"
);
}
}
});
eprintln!("is_opaque_rgba8: {report}");
}
#[test]
fn grayscale_rgba8_matches_scalar_all_tiers() {
let report = for_each_token_permutation(CompileTimePolicy::Warn, |_perm| {
for &n in &[0usize, 1, 4, 16, 17, 64, 200, 4099] {
let v = rgba_pattern(n, |_, _| {});
assert_eq!(
super::is_grayscale_rgba8(&v),
scalar_is_grayscale_rgba8(&v),
"n={n} all-gray"
);
if n > 5 {
let mut v = rgba_pattern(n, |_, _| {});
v[5 * 4] = 1;
v[5 * 4 + 1] = 2;
v[5 * 4 + 2] = 3;
assert_eq!(
super::is_grayscale_rgba8(&v),
scalar_is_grayscale_rgba8(&v),
"n={n} colorful pixel 5"
);
}
if n > 5 {
let mut v = rgba_pattern(n, |_, _| {});
v[5 * 4 + 1] = v[5 * 4].wrapping_add(1);
assert_eq!(
super::is_grayscale_rgba8(&v),
scalar_is_grayscale_rgba8(&v),
"n={n} g=r+1 at pixel 5"
);
}
}
});
eprintln!("is_grayscale_rgba8: {report}");
}
#[test]
fn grayscale_rgb8_matches_scalar_all_tiers() {
let report = for_each_token_permutation(CompileTimePolicy::Warn, |_perm| {
for &n in &[0usize, 1, 3, 16, 64, 200, 4099] {
let mut v = Vec::with_capacity(n * 3);
for i in 0..n {
let g = (i * 7 + 3) as u8;
v.extend_from_slice(&[g, g, g]);
}
assert_eq!(
super::is_grayscale_rgb8(&v),
scalar_is_grayscale_rgb8(&v),
"n={n} all-gray"
);
if n > 80 {
let mut v2 = v.clone();
v2[80 * 3 + 1] = v2[80 * 3].wrapping_add(1);
assert_eq!(
super::is_grayscale_rgb8(&v2),
scalar_is_grayscale_rgb8(&v2),
"n={n} pixel 80 g+=1"
);
}
}
});
eprintln!("is_grayscale_rgb8: {report}");
}
#[test]
fn bit_replication_matches_scalar_all_tiers() {
let report = for_each_token_permutation(CompileTimePolicy::Warn, |_perm| {
for &n in &[0usize, 2, 4, 16, 64, 200, 4096] {
let mut v: Vec<u16> = Vec::with_capacity(n);
for i in 0..n {
let b = (i * 11 + 7) as u8;
v.push(u16::from(b) * 0x0101);
}
assert_eq!(
super::bit_replication_lossless_u16(&v),
scalar_bit_replication_u16(&v),
"n={n} replicated"
);
if n > 30 {
v[30] = v[30].wrapping_add(1); assert_eq!(
super::bit_replication_lossless_u16(&v),
scalar_bit_replication_u16(&v),
"n={n} broken at 30"
);
}
}
});
eprintln!("bit_replication_lossless_u16: {report}");
}
#[test]
fn empty_buffers_are_vacuously_true_for_every_predicate() {
assert!(super::is_opaque_rgba8(&[]));
assert!(super::is_grayscale_rgba8(&[]));
assert!(super::is_grayscale_rgb8(&[]));
assert!(super::is_opaque_ga8(&[]));
assert!(super::is_opaque_rgba16(&[]));
assert!(super::is_grayscale_rgba16(&[]));
assert!(super::is_grayscale_rgb16(&[]));
assert!(super::is_opaque_ga16(&[]));
assert!(super::bit_replication_lossless_u16(&[]));
assert!(super::is_opaque_rgba_f32(&[]));
assert!(super::is_grayscale_rgba_f32(&[]));
assert!(super::is_grayscale_rgb_f32(&[]));
assert!(super::is_opaque_ga_f32(&[]));
let r = super::fused_predicates_rgba8(&[], super::FusedRequest::all());
assert!(r.is_opaque && r.is_grayscale);
let r = super::fused_predicates_rgba8_cg(&[], super::FusedRequest::all());
assert!(r.is_opaque && r.is_grayscale);
}
#[test]
fn is_opaque_rgba8_at_simd_boundaries() {
for &n_pixels in &[15usize, 16, 17, 31, 32, 33, 63, 64, 65] {
let mut v = vec![0u8; n_pixels * 4];
for i in 0..n_pixels {
v[i * 4 + 3] = 255;
}
assert!(super::is_opaque_rgba8(&v), "all-opaque at n={n_pixels}");
if n_pixels > 0 {
v[(n_pixels - 1) * 4 + 3] = 128;
assert!(
!super::is_opaque_rgba8(&v),
"last-pixel-non-opaque at n={n_pixels}"
);
}
}
}
#[test]
fn is_grayscale_rgba8_at_shifted_load_boundaries() {
for &n_pixels in &[16usize, 17, 32, 33, 48, 64, 65, 80] {
let mut v = vec![0u8; n_pixels * 4];
for i in 0..n_pixels {
let g = ((i * 11) & 0xFF) as u8;
v[i * 4] = g;
v[i * 4 + 1] = g;
v[i * 4 + 2] = g;
v[i * 4 + 3] = 255;
}
assert!(super::is_grayscale_rgba8(&v), "all-gray at n={n_pixels}");
if n_pixels > 1 {
v[(n_pixels - 1) * 4 + 1] = v[(n_pixels - 1) * 4].wrapping_add(1);
assert!(
!super::is_grayscale_rgba8(&v),
"last-pixel-color at n={n_pixels}"
);
}
}
}
#[test]
fn is_grayscale_rgb8_at_super_chunk_boundaries() {
for &n_pixels in &[63usize, 64, 65, 127, 128, 129, 191, 192, 193] {
let mut v = vec![0u8; n_pixels * 3];
for i in 0..n_pixels {
let g = ((i * 7) & 0xFF) as u8;
v[i * 3] = g;
v[i * 3 + 1] = g;
v[i * 3 + 2] = g;
}
assert!(super::is_grayscale_rgb8(&v), "all-gray at n={n_pixels}");
let mid = n_pixels / 2;
if n_pixels > 5 {
v[mid * 3 + 1] = v[mid * 3].wrapping_add(1);
assert!(
!super::is_grayscale_rgb8(&v),
"mid-pixel-color at n={n_pixels}"
);
}
}
}
#[test]
fn bit_replication_at_simd_boundaries() {
for &n_samples in &[31usize, 32, 33, 63, 64, 65] {
let mut v = vec![0u16; n_samples];
for (i, s) in v.iter_mut().enumerate() {
let b = (i * 11 + 7) as u8;
*s = u16::from(b) * 0x0101;
}
assert!(
super::bit_replication_lossless_u16(&v),
"replicated at n={n_samples}"
);
if n_samples > 0 {
v[n_samples - 1] ^= 0x0001;
assert!(
!super::bit_replication_lossless_u16(&v),
"last-sample-broken at n={n_samples}"
);
}
}
}
#[test]
fn is_opaque_rgba8_breaks_at_every_position_class() {
let make_buf = || {
let mut v = vec![0u8; 32 * 4];
for i in 0..32 {
v[i * 4] = 50;
v[i * 4 + 1] = 60;
v[i * 4 + 2] = 70;
v[i * 4 + 3] = 255;
}
v
};
let mut v = make_buf();
v[3] = 0;
assert!(!super::is_opaque_rgba8(&v));
let mut v = make_buf();
v[15 * 4 + 3] = 254;
assert!(!super::is_opaque_rgba8(&v));
let mut v = make_buf();
v[16 * 4 + 3] = 0;
assert!(!super::is_opaque_rgba8(&v));
let mut v = make_buf();
v[31 * 4 + 3] = 200;
assert!(!super::is_opaque_rgba8(&v));
}
#[test]
fn predicates_handle_single_pixel_inputs() {
assert!(super::is_opaque_rgba8(&[10, 20, 30, 255]));
assert!(!super::is_opaque_rgba8(&[10, 20, 30, 254]));
assert!(super::is_grayscale_rgba8(&[42, 42, 42, 255]));
assert!(!super::is_grayscale_rgba8(&[42, 43, 42, 255]));
assert!(super::is_grayscale_rgb8(&[42, 42, 42]));
assert!(!super::is_grayscale_rgb8(&[42, 42, 43]));
assert!(super::is_opaque_ga8(&[42, 255]));
assert!(!super::is_opaque_ga8(&[42, 254]));
assert!(super::bit_replication_lossless_u16(&[0x4242]));
assert!(!super::bit_replication_lossless_u16(&[0x4243]));
}
#[test]
fn ga_predicates_handle_extreme_alphas() {
let v = [10u8, 0, 50, 0, 100, 0, 200, 0];
assert!(!super::is_opaque_ga8(&v));
let v = [10u8, 255, 50, 255, 100, 255, 200, 255];
assert!(super::is_opaque_ga8(&v));
let v = [10u8, 128, 50, 128];
assert!(!super::is_opaque_ga8(&v));
}
#[test]
fn bit_replication_handles_extreme_pairs() {
assert!(super::bit_replication_lossless_u16(&[0x0000]));
assert!(super::bit_replication_lossless_u16(&[0xFFFF]));
assert!(!super::bit_replication_lossless_u16(&[0x0001]));
assert!(!super::bit_replication_lossless_u16(&[0x0100]));
assert!(super::bit_replication_lossless_u16(&[0x7F7F]));
assert!(super::bit_replication_lossless_u16(&[0x8080]));
assert!(!super::bit_replication_lossless_u16(&[0xFEFE, 0xFE00]));
}
#[test]
fn f32_predicates_handle_nan_inf() {
assert!(!super::is_opaque_rgba_f32(&[0.5, 0.5, 0.5, f32::NAN]));
assert!(!super::is_grayscale_rgba_f32(&[f32::NAN, 0.5, 0.5, 1.0]));
}
#[test]
fn f32_predicates_at_simd_boundaries() {
for &n_pixels in &[3usize, 4, 5, 7, 8, 9] {
let mut v = vec![0.0_f32; n_pixels * 4];
for i in 0..n_pixels {
let g = i as f32 * 0.1;
v[i * 4] = g;
v[i * 4 + 1] = g;
v[i * 4 + 2] = g;
v[i * 4 + 3] = 1.0;
}
assert!(super::is_opaque_rgba_f32(&v), "all-opaque at n={n_pixels}");
assert!(super::is_grayscale_rgba_f32(&v), "all-gray at n={n_pixels}");
if n_pixels > 0 {
v[(n_pixels - 1) * 4 + 3] = 0.5;
assert!(
!super::is_opaque_rgba_f32(&v),
"last-pixel-non-opaque at n={n_pixels}"
);
}
}
}
}