vyre 0.4.0

GPU compute intermediate representation with a standard operation library
Documentation
//! SipHash-1-3 CPU reference implementation.

// sip_round.rs
pub fn sip_round(v0: &mut u64, v1: &mut u64, v2: &mut u64, v3: &mut u64) {
    *v0 = v0.wrapping_add(*v1);
    *v1 = v1.rotate_left(13);
    *v1 ^= *v0;
    *v0 = v0.rotate_left(32);
    *v2 = v2.wrapping_add(*v3);
    *v3 = v3.rotate_left(16);
    *v3 ^= *v2;
    *v0 = v0.wrapping_add(*v3);
    *v3 = v3.rotate_left(21);
    *v3 ^= *v0;
    *v2 = v2.wrapping_add(*v1);
    *v1 = v1.rotate_left(17);
    *v1 ^= *v2;
    *v2 = v2.rotate_left(32);
}

// siphash13.rs
/// Compute SipHash-1-3 with a 64-bit key expanded into the 128-bit key space.
#[must_use]
pub(crate) fn siphash13(msg: &[u8], key: u64) -> u64 {
    let k0 = key;
    let k1 = key.rotate_left(32) ^ 0x736f6d6570736575;
    let mut v0 = 0x736f6d6570736575 ^ k0;
    let mut v1 = 0x646f72616e646f6d ^ k1;
    let mut v2 = 0x6c7967656e657261 ^ k0;
    let mut v3 = 0x7465646279746573 ^ k1;

    let mut chunks = msg.chunks_exact(8);
    for chunk in &mut chunks {
        let m = u64::from_le_bytes([
            chunk[0], chunk[1], chunk[2], chunk[3], chunk[4], chunk[5], chunk[6], chunk[7],
        ]);
        v3 ^= m;
        sip_round(&mut v0, &mut v1, &mut v2, &mut v3);
        v0 ^= m;
    }

    let rem = chunks.remainder();
    let mut b = (msg.len() as u64) << 56;
    for (i, byte) in rem.iter().enumerate() {
        b |= u64::from(*byte) << (8 * i);
    }
    v3 ^= b;
    sip_round(&mut v0, &mut v1, &mut v2, &mut v3);
    v0 ^= b;
    v2 ^= 0xff;
    for _ in 0..3 {
        sip_round(&mut v0, &mut v1, &mut v2, &mut v3);
    }
    v0 ^ v1 ^ v2 ^ v3
}