1 use super::Vector;
2 use crate::xxhash3::{primes::PRIME32_1, SliceBackport as _};
3
4 #[derive(Copy, Clone)]
5 pub struct Impl;
6
7 impl Vector for Impl {
8 #[inline]
round_scramble(&self, acc: &mut [u64; 8], secret_end: &[u8; 64])9 fn round_scramble(&self, acc: &mut [u64; 8], secret_end: &[u8; 64]) {
10 let (last, _) = secret_end.bp_as_chunks();
11 let last = last.iter().copied().map(u64::from_le_bytes);
12
13 for (acc, secret) in acc.iter_mut().zip(last) {
14 *acc ^= *acc >> 47;
15 *acc ^= secret;
16 *acc = acc.wrapping_mul(PRIME32_1);
17 }
18 }
19
20 #[inline]
accumulate(&self, acc: &mut [u64; 8], stripe: &[u8; 64], secret: &[u8; 64])21 fn accumulate(&self, acc: &mut [u64; 8], stripe: &[u8; 64], secret: &[u8; 64]) {
22 let (stripe, _) = stripe.bp_as_chunks();
23 let (secret, _) = secret.bp_as_chunks();
24
25 for i in 0..8 {
26 let stripe = u64::from_le_bytes(stripe[i]);
27 let secret = u64::from_le_bytes(secret[i]);
28
29 let value = stripe ^ secret;
30 acc[i ^ 1] = acc[i ^ 1].wrapping_add(stripe);
31 acc[i] = multiply_64_as_32_and_add(value, value >> 32, acc[i]);
32 }
33 }
34 }
35
36 #[inline]
37 #[cfg(any(miri, not(target_arch = "aarch64")))]
multiply_64_as_32_and_add(lhs: u64, rhs: u64, acc: u64) -> u6438 fn multiply_64_as_32_and_add(lhs: u64, rhs: u64, acc: u64) -> u64 {
39 use super::IntoU64;
40
41 let lhs = (lhs as u32).into_u64();
42 let rhs = (rhs as u32).into_u64();
43
44 let product = lhs.wrapping_mul(rhs);
45 acc.wrapping_add(product)
46 }
47
48 #[inline]
49 // https://github.com/Cyan4973/xxHash/blob/d5fe4f54c47bc8b8e76c6da9146c32d5c720cd79/xxhash.h#L5595-L5610
50 // https://github.com/llvm/llvm-project/issues/98481
51 #[cfg(all(not(miri), target_arch = "aarch64"))]
multiply_64_as_32_and_add(lhs: u64, rhs: u64, acc: u64) -> u6452 fn multiply_64_as_32_and_add(lhs: u64, rhs: u64, acc: u64) -> u64 {
53 let res;
54
55 // Safety: We only compute using our argument values and do
56 // not change memory.
57 unsafe {
58 core::arch::asm!(
59 "umaddl {res}, {lhs:w}, {rhs:w}, {acc}",
60 lhs = in(reg) lhs,
61 rhs = in(reg) rhs,
62 acc = in(reg) acc,
63 res = out(reg) res,
64 options(pure, nomem, nostack),
65 )
66 }
67
68 res
69 }
70