In my PRNG research I found this at Sebastiano Vigna's website here, towards the bottom.
Code: Select all
#include <stdint.h>
static inline double to_double(uint64_t x) {
const union { uint64_t i; double d; } u = { .i = UINT64_C(0x3FF) << 52 | x >> 12 };
return u.d - 1.0;
}
I am using it to convert 2 x 32-bit unsigned integers from a 32-bit output PRNG to a 64-bit Double.
To test it I total 10^7 random Ulong pairs and then determine the average, aiming at 0.5. On one run I got 0.5000907638144706 in 0.36 seconds, so it is fairly swift.
Code: Select all
Const DoubleBits = 1023ull Shl 52
Union UllToDbl
i As Ulongint
d As Double
End Union
' Adaptation of mkulongint by, I think, dodicat?
' In practice n1 And n2 will be from a PRNG Ulong Output
' Vigna's code within the following
Function TwoUlongsToDouble( n1 as Ulong, n2 as Ulong ) as Double
Dim Ans As UllToDbl
Dim As Ulongint res
Cast(Ulong Ptr,@res)[0]=n1
Cast(Ulong Ptr,@res)[1]=n2
Ans.i = DoubleBits Or (res Shr 12)
Return Ans.d - 1.0
End Function
Randomize
Dim As Ulong i
Dim As Double t, tot
' CULng(Rnd*&hFFFFFFFFul) by MrSwiss
t = Timer
For i = 1 To 10^7
tot += TwoUlongsToDouble( CULng(Rnd*&hFFFFFFFFul), CULng(Rnd*&hFFFFFFFFul) )
Next
t = Timer - t
Print tot/10^7, t
Sleep