#![allow(clippy::indexing_slicing)]
use super::{BLOCK_WORDS, P_LANE_WORDS};
pub(super) type CompressFn =
unsafe fn(dst: &mut [u64; BLOCK_WORDS], x: &[u64; BLOCK_WORDS], y: &[u64; BLOCK_WORDS], xor_into: bool);
macro_rules! gb_direct {
($a:expr, $b:expr, $c:expr, $d:expr) => {{
let t1 = ($a & 0xFFFF_FFFFu64).wrapping_mul($b & 0xFFFF_FFFFu64);
$a = $a.wrapping_add($b).wrapping_add(t1.wrapping_mul(2));
$d = ($d ^ $a).rotate_right(32);
let t2 = ($c & 0xFFFF_FFFFu64).wrapping_mul($d & 0xFFFF_FFFFu64);
$c = $c.wrapping_add($d).wrapping_add(t2.wrapping_mul(2));
$b = ($b ^ $c).rotate_right(24);
let t3 = ($a & 0xFFFF_FFFFu64).wrapping_mul($b & 0xFFFF_FFFFu64);
$a = $a.wrapping_add($b).wrapping_add(t3.wrapping_mul(2));
$d = ($d ^ $a).rotate_right(16);
let t4 = ($c & 0xFFFF_FFFFu64).wrapping_mul($d & 0xFFFF_FFFFu64);
$c = $c.wrapping_add($d).wrapping_add(t4.wrapping_mul(2));
$b = ($b ^ $c).rotate_right(63);
}};
}
macro_rules! p_direct {
(
$v0:expr, $v1:expr, $v2:expr, $v3:expr,
$v4:expr, $v5:expr, $v6:expr, $v7:expr,
$v8:expr, $v9:expr, $v10:expr, $v11:expr,
$v12:expr, $v13:expr, $v14:expr, $v15:expr $(,)?
) => {{
gb_direct!($v0, $v4, $v8, $v12);
gb_direct!($v1, $v5, $v9, $v13);
gb_direct!($v2, $v6, $v10, $v14);
gb_direct!($v3, $v7, $v11, $v15);
gb_direct!($v0, $v5, $v10, $v15);
gb_direct!($v1, $v6, $v11, $v12);
gb_direct!($v2, $v7, $v8, $v13);
gb_direct!($v3, $v4, $v9, $v14);
}};
}
#[inline(always)]
pub(super) unsafe fn compress_portable(
dst: &mut [u64; BLOCK_WORDS],
x: &[u64; BLOCK_WORDS],
y: &[u64; BLOCK_WORDS],
xor_into: bool,
) {
let mut r = [0u64; BLOCK_WORDS];
for i in 0..BLOCK_WORDS {
r[i] = x[i] ^ y[i];
}
let mut q = r;
for chunk in q.chunks_exact_mut(P_LANE_WORDS) {
p_direct!(
chunk[0], chunk[1], chunk[2], chunk[3], chunk[4], chunk[5], chunk[6], chunk[7], chunk[8], chunk[9], chunk[10],
chunk[11], chunk[12], chunk[13], chunk[14], chunk[15],
);
}
for col in 0usize..8 {
let base = col * 2;
p_direct!(
q[base],
q[base + 1],
q[base + 16],
q[base + 17],
q[base + 32],
q[base + 33],
q[base + 48],
q[base + 49],
q[base + 64],
q[base + 65],
q[base + 80],
q[base + 81],
q[base + 96],
q[base + 97],
q[base + 112],
q[base + 113],
);
}
if xor_into {
for i in 0..BLOCK_WORDS {
dst[i] ^= q[i] ^ r[i];
}
} else {
for i in 0..BLOCK_WORDS {
dst[i] = q[i] ^ r[i];
}
}
}