1inline uint mulhilo_(uint a, uint b, uint* hip) {
2    ulong product = ((ulong)a)*((ulong)b);
3    *hip = product >> 32;
4    return (uint)product;
5}
6inline uint2 r4inc_(uint2 key) {
7    key.x += ((uint)0x9E3779B9); key.y += ((uint)0xBB67AE85); return key;
8}
9inline uint4 r4iter_(uint4 ctr, uint2 key) {
10    uint4 out;
11    uint hi0, hi1;
12    uint lo0 = mulhilo_(((uint)0xD2511F53), ctr.x, &hi0);
13    uint lo1 = mulhilo_(((uint)0xCD9E8D57), ctr.z, &hi1);
14    out.x = hi1 ^ ctr.y ^ key.x;
15    out.y = lo1;
16    out.z = hi0 ^ ctr.w ^ key.y;
17    out.w = lo0;
18    return out;
19}
20inline uint4 rnd4_(uint4 ctr, uint2 key) {
21    ctr = r4iter_(ctr, key);
22    key = r4inc_(key); ctr = r4iter_(ctr, key);
23    key = r4inc_(key); ctr = r4iter_(ctr, key);
24    key = r4inc_(key); ctr = r4iter_(ctr, key);
25    key = r4inc_(key); ctr = r4iter_(ctr, key);
26    key = r4inc_(key); ctr = r4iter_(ctr, key);
27    key = r4inc_(key); ctr = r4iter_(ctr, key);
28    key = r4inc_(key); ctr = r4iter_(ctr, key);
29    key = r4inc_(key); ctr = r4iter_(ctr, key);
30    key = r4inc_(key); ctr = r4iter_(ctr, key);
31    return ctr;
32}
33uint4 rnd_uint4(const uint seed,
34        const uint c0, const uint c1, const uint c2, const uint c3) {
35    return rnd4_((uint4)(c0, c1, c2, c3), (uint2)(seed, 0xCAFEF00D));
36}
37