#[cfg(feature = "simd")]
use crate::simd::clock_mix_avx2;
use crate::constants::{ROTATION_SCHEDULE, SBOX};
use crate::utils::rotl64;
#[inline]
pub fn clock_mix(message: &mut [u64; 16]) {
#[cfg(feature = "simd")]
{
clock_mix_avx2(message);
}
#[cfg(not(feature = "simd"))]
{
for i in 0..16 {
let next_idx = (i + 1) % 16;
let rotation = ROTATION_SCHEDULE[i];
message[i] ^= rotl64(message[next_idx], rotation);
}
for i in 0..16 {
let sbox_idx = (message[i] & 0xFF) as usize;
message[i] = message[i].wrapping_add(SBOX[sbox_idx] as u64);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_clock_mix_basic() {
let mut msg = [0u64; 16];
msg[0] = 0x1234567890ABCDEF;
let original = msg;
clock_mix(&mut msg);
assert_ne!(msg, original);
}
#[test]
fn test_clock_mix_avalanche() {
let mut msg1 = [0u64; 16];
let mut msg2 = [0u64; 16];
msg1[0] = 0x0000000000000000;
msg2[0] = 0x0000000000000001;
clock_mix(&mut msg1);
clock_mix(&mut msg2);
assert_ne!(msg1, msg2);
}
#[test]
fn test_clock_mix_deterministic() {
let mut msg = [0u64; 16];
msg[0] = 0xDEADBEEFCAFEBABE;
let mut msg_copy = msg;
clock_mix(&mut msg);
clock_mix(&mut msg_copy);
assert_eq!(msg, msg_copy);
}
}