pub trait Lanes: Copy {
const N: usize;
const FLAT_ROUNDS: bool = true;
fn splat(v: u32) -> Self;
fn load(v: &[u32]) -> Self;
fn store(self, out: &mut [u32]);
fn add(self, o: Self) -> Self;
fn xor(self, o: Self) -> Self;
fn and(self, o: Self) -> Self;
fn not_and(self, o: Self) -> Self;
fn shr<const B: u32>(self) -> Self;
fn rotr<const B: u32>(self) -> Self;
#[inline(always)]
fn xor3(self, b: Self, c: Self) -> Self {
self.xor(b).xor(c)
}
#[inline(always)]
fn ch(self, y: Self, z: Self) -> Self {
self.and(y).xor(self.not_and(z))
}
#[inline(always)]
fn maj(self, y: Self, z: Self) -> Self {
y.xor(self.xor(y).and(y.xor(z)))
}
#[inline(always)]
unsafe fn transpose(ptrs: &[*const u8], n: usize) -> [Self; 16] {
let mut scratch = [0u32; 16];
let mut w = [Self::splat(0); 16];
for (j, wj) in w.iter_mut().enumerate() {
for (lane, s) in scratch[..n].iter_mut().enumerate() {
let b = ptrs[lane].add(4 * j);
*s = u32::from_be_bytes([*b, *b.add(1), *b.add(2), *b.add(3)]);
}
let fill = scratch[0];
scratch[n..Self::N].fill(fill);
*wj = Self::load(&scratch[..Self::N]);
}
w
}
}
#[derive(Clone, Copy)]
pub struct Scalar<const N: usize>(pub [u32; N]);
impl<const N: usize> Lanes for Scalar<N> {
const N: usize = N;
const FLAT_ROUNDS: bool = false;
#[inline(always)]
fn splat(v: u32) -> Self {
Scalar([v; N])
}
#[inline(always)]
fn load(v: &[u32]) -> Self {
debug_assert_eq!(v.len(), N);
let mut a = [0u32; N];
a.copy_from_slice(v);
Scalar(a)
}
#[inline(always)]
fn store(self, out: &mut [u32]) {
debug_assert_eq!(out.len(), N);
out.copy_from_slice(&self.0);
}
#[inline(always)]
fn add(self, o: Self) -> Self {
let mut a = self.0;
for (x, y) in a.iter_mut().zip(o.0) {
*x = x.wrapping_add(y);
}
Scalar(a)
}
#[inline(always)]
fn xor(self, o: Self) -> Self {
let mut a = self.0;
for (x, y) in a.iter_mut().zip(o.0) {
*x ^= y;
}
Scalar(a)
}
#[inline(always)]
fn and(self, o: Self) -> Self {
let mut a = self.0;
for (x, y) in a.iter_mut().zip(o.0) {
*x &= y;
}
Scalar(a)
}
#[inline(always)]
fn not_and(self, o: Self) -> Self {
let mut a = self.0;
for (x, y) in a.iter_mut().zip(o.0) {
*x = !*x & y;
}
Scalar(a)
}
#[inline(always)]
fn shr<const B: u32>(self) -> Self {
let mut a = self.0;
for x in a.iter_mut() {
*x >>= B;
}
Scalar(a)
}
#[inline(always)]
fn rotr<const B: u32>(self) -> Self {
let mut a = self.0;
for x in a.iter_mut() {
*x = x.rotate_right(B);
}
Scalar(a)
}
}