I think I heard that most pc processors always calculate the upper mult, even when not asked... not sure for what % that is true, but it does seem to be quite fast on most CPUs. https://github.com/wangyi-fudan/wyhash The mix is prime number where each byte has 4 zeros and ones. As I mentioned, I tried to tinker with it mulitple times but I just end up destroying it's speed. https://tom-kaitchuck.medium.com/designing-a-new-prng-1c4ffd27124d And this was my intro to MWC, but the math is a bit above...
I think you got how they work. They are still available on the link I posted. Wrote C long ago, here is LLM translation, it assumes __uint128_t #define WYR64_MIX 0x8bb84b93962eacc9ULL #define WYR64_INC 0x2d358dccaa6c78a5ULL #define ODD_PHI_64 0x9e3779b97f4a7c15ULL typedef uint64_t WYR64; WYR64 WYR64_init(uint64_t seed) { return (seed + WYR64_MIX) * WYR64_INC * ODD_PHI_64; } uint64_t WYR64_u64(WYR64 *r) { *r += WYR64_INC; __uint128_t mix = (__uint128_t)(*r) * (__uint128_t)(*r ^ WYR64_MIX); return...
Sorry for the late reply! Interesting ones, hope you had fun. This is how fast they run on my M2 Pro (ns/out): Mul1: 0.7171630859375 Mul2: 0.8544921875 Mul3: 1.129150390625 Mul4: 1.129150390625 WYRand: 0.3509521484375 MWCP: 0.5645751953125 SFC: 0.885009765625 WYRand: r^ += WYR64_INC mix := u128(r^) * u128(r^ ~ WYR64_MIX) return u64(mix >> 64) ~ u64(mix) MWCP: mix := u128(r[1]) * u128(0xfeb344657c0af413) + u128(r[0]) r^ = {u64(mix >> 64), r[2], r[3], u64(mix)} return u64(mix >> 64) + u64(mix) Odin...
Sorry for the late reply! Interesting ones, hope you had fun. This is how fast they run on my M2 Pro (ns/out): ` Mul1: 0.7171630859375 Mul2: 0.8544921875 Mul3: 1.129150390625 Mul4: 1.129150390625 WYRand: 0.3509521484375 MWCP: 0.5645751953125 SFC: 0.885009765625 WYRand: r^ += WYR64_INC mix := u128(r^) * u128(r^ ~ WYR64_MIX) return u64(mix >> 64) ~ u64(mix) MWCP: mix := u128(r[1]) * u128(0xfeb344657c0af413) + u128(r[0]) r^ = {u64(mix >> 64), r[2], r[3], u64(mix)} return u64(mix >> 64) + u64(mix) `...
I got it... I said first 5 outputs after the init, while you are showing the state after init... this is good then: d8 1c 84 05 51 As for why we are getting different tests results is eather that your new version for mod3n is different or that we feed the test differently.... So, when is the new version coming out? Haha
Ah, you are using left rotate... then I am really confused, I will re-check. Sorry for taking you time like this haha.
Funny we posted at the same time... Maybe the rotates are different, I am using left rotate...
const Uint64 K = 0x92ec64765925a395ull; a ^= b; a = rotate(a, 13); b = b + (b << 3) + Uint32(K); a *= K; return a; This is more than twice slower than MWC on my Arm Mac. But it is an interesting approach, thanks for sharing! I see you are also not a fan of LFSRs haha. Uint16 state[5]; static Uint16 _bswap16(Uint16 v) { return (Uint16((v >> 0) & 15) << 12) | (Uint16((v >> 4) & 15) << 8) | (Uint16((v >> 8) & 15) << 4) | (Uint16((v >> 12) & 15) << 0); } Uint16 raw16() { Uint16 tmp = state[0] - state[1];...