#[cfg(test)]
mod tests {
extern crate alloc;
use crate::simd::dispatch::*;
use crate::simd::scalar::*;
use alloc::vec::Vec;
#[test]
fn test_simd_clock_mix_consistency() {
let mut msg1 = [0u64; 16];
let mut msg2 = [0u64; 16];
for i in 0..16 {
msg1[i] = (i as u64).wrapping_mul(0x123456789ABCDEF0);
msg2[i] = msg1[i];
}
scalar_clock_mix(&mut msg1);
clock_mix_avx2(&mut msg2);
if msg1 != msg2 {
println!("Input: {:?}", [0u64; 16].iter().enumerate().map(|(i, _)| (i as u64).wrapping_mul(0x123456789ABCDEF0)).collect::<Vec<_>>());
println!("Scalar result: {:?}", msg1);
println!("AVX2 result: {:?}", msg2);
for i in 0..16 {
if msg1[i] != msg2[i] {
println!("Difference at [{}]: Scalar={:016x}, AVX2={:016x}", i, msg1[i], msg2[i]);
}
}
}
assert_eq!(
msg1, msg2,
"SIMD and scalar implementations should produce identical results"
);
}
#[test]
fn test_simd_edge_cases() {
let mut msg1 = [0u64; 16];
let mut msg2 = [0u64; 16];
scalar_clock_mix(&mut msg1);
clock_mix_avx2(&mut msg2);
assert_eq!(msg1, msg2, "All zeros case should work");
let mut msg1 = [u64::MAX; 16];
let mut msg2 = [u64::MAX; 16];
scalar_clock_mix(&mut msg1);
clock_mix_avx2(&mut msg2);
assert_eq!(msg1, msg2, "All ones case should work");
let mut msg1 = [0u64; 16];
let mut msg2 = [0u64; 16];
for i in 0..16 {
let val = if i % 2 == 0 {
0xAAAAAAAAAAAAAAAA
} else {
0x5555555555555555
};
msg1[i] = val;
msg2[i] = val;
}
scalar_clock_mix(&mut msg1);
clock_mix_avx2(&mut msg2);
assert_eq!(msg1, msg2, "Alternating pattern should work");
}
#[test]
fn test_simd_no_memory_corruption() {
let test_data = [0x123456789ABCDEF0u64; 16];
let mut data = test_data.clone();
clock_mix_avx2(&mut data);
assert_ne!(data, test_data, "Test data should have been modified");
let mut scalar_data = test_data;
scalar_clock_mix(&mut scalar_data);
assert_eq!(data, scalar_data, "SIMD result should match scalar");
}
#[test]
fn test_simd_multiple_calls_consistency() {
let mut msg1 = [0xCAFEBABEu64; 16];
let mut msg2 = [0xCAFEBABEu64; 16];
for _ in 0..3 {
clock_mix_avx2(&mut msg1);
scalar_clock_mix(&mut msg2);
}
assert_eq!(
msg1, msg2,
"Multiple applications should maintain consistency"
);
}
#[test]
fn test_simd_consistency_under_modification() {
let patterns = [
[0u64; 16], [u64::MAX; 16], [1u64 << 63; 16], [0xAAAAAAAAAAAAAAAA; 16], [0x5555555555555555; 16], ];
for (i, pattern) in patterns.iter().enumerate() {
let mut msg1 = *pattern;
let mut msg2 = *pattern;
scalar_clock_mix(&mut msg1);
clock_mix_avx2(&mut msg2);
assert_eq!(
msg1, msg2,
"Pattern {} should produce consistent results",
i
);
}
}
#[test]
fn test_endianness_handling() {
let block = [0u8; 128];
let mut state1 = [0u64; 8];
let mut state2 = [0u64; 8];
for i in 0..8 {
state1[i] = (i as u64) * 0x1111111111111111;
state2[i] = state1[i];
}
process_block_simd_scalar(&block, &mut state1);
process_block_simd(&block, &mut state2);
assert_eq!(
state1, state2,
"Block processing should handle endianness correctly"
);
}
fn process_block_simd_scalar(block: &[u8; 128], state: &mut [u64; 8]) {
let mut words = [0u64; 16];
for i in 0..16 {
let offset = i * 8;
words[i] = u64::from_le_bytes([
block[offset],
block[offset + 1],
block[offset + 2],
block[offset + 3],
block[offset + 4],
block[offset + 5],
block[offset + 6],
block[offset + 7],
]);
}
scalar_clock_mix(&mut words);
for i in 0..8 {
state[i] = state[i].wrapping_add(words[i]);
let rot_idx = (i + 4) % 8;
state[i] ^= crate::utils::rotl64(state[rot_idx], 17);
}
crate::clockpermute::clock_permute(state);
}
}