1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use typenum::{Unsigned, U2, U4, U10, U32};
use generic_array::{ArrayLength, GenericArray};
type Ph<N, W, R> = Philox<N, W, R, <N as std::ops::Div<U2>>::Output>;
pub type Philox4x32_10 = Ph<U4, U32, U10>;
pub struct Philox<N: Unsigned + ArrayLength<u32>, W: Unsigned, R: Unsigned, KN: ArrayLength<u32>> {
_m0: std::marker::PhantomData<N>,
_m1: std::marker::PhantomData<KN>,
_m2: std::marker::PhantomData<W>,
_m3: std::marker::PhantomData<R>,
}
struct HiLo(u32, u32);
fn mulhilo(a: u32, b: u32) -> HiLo {
let p = (a as u64).wrapping_mul(b as u64);
HiLo((p >> 32) as u32, p as u32)
}
impl<N: Unsigned + ArrayLength<u32>, W: Unsigned, R: Unsigned, KN: ArrayLength<u32>> Philox<N, W, R, KN> {
pub fn next(&mut self, mut key: GenericArray<u32, KN>, mut ctr: GenericArray<u32, N>) -> GenericArray<u32, N> {
for _ in 0..R::USIZE {
self.round(&mut key, &mut ctr);
self.update_key(&mut key);
}
ctr
}
fn round(&mut self, key: &mut GenericArray<u32, KN>, mut ctr: &mut GenericArray<u32, N>) {
let c0 = ctr.clone();
#[allow(non_upper_case_globals)] const PHILOX_M4x32_0: u32 = 0xD2511F53;
#[allow(non_upper_case_globals)] const PHILOX_M4x32_1: u32 = 0xCD9E8D57;
let HiLo(hi0, lo0) = mulhilo(PHILOX_M4x32_0, c0[0]);
let HiLo(hi1, lo1) = mulhilo(PHILOX_M4x32_1, c0[2]);
let c1 = &mut ctr;
c1[0] = hi1 ^ c0[1] ^ key[0];
c1[1] = lo1;
c1[2] = hi0 ^ c0[3] ^ key[1];
c1[3] = lo0;
}
fn update_key(&mut self, key: &mut GenericArray<u32, KN>) {
const C0: u32 = 0x9E3779B9;
const C1: u32 = 0xBB67AE85;
key[0] = key[0].wrapping_add(C0);
key[1] = key[1].wrapping_add(C1);
}
}
impl<N: Unsigned + ArrayLength<u32>, W: Unsigned, R: Unsigned, KN: Unsigned + ArrayLength<u32>> Default for Philox<N, W, R, KN> {
fn default() -> Self {
assert_eq!(W::to_usize(), 32);
Self {
_m0: Default::default(),
_m1: Default::default(),
_m2: Default::default(),
_m3: Default::default(),
}
}
}
#[cfg(test)] mod test;