Throughput in MHZ (gcc -O3). First in pair is source code; second is library
Code: Select all
32-bit 64-bit
Rnd6 301/200 312/188
Range Int 302/130 303/131
Range float 315/ 74 318/ 76
There is little difference between 32-bit and 64-bit whether source code or library.
The throughput with FB #5 in 32-bit mode is 0.5MHz.
I am not going to drop the library approach and leave you with it, so here is the source code.
Although Rnd6 is now a viable generator in its own right, it is really a FB #5 replacement. CryptoRndII with its twin buffering and thread pooling has twice the throughput. Rnd6 is ideal for initializing applications where only a small number of [0,1)/range values are required. Rnd6 is now 3.75 times faster than Mersenne Twister.
I wondered whether the 40*1024*4 and 40*1024-1 would be replaced by 163840 and 40959 respectively. They were, but not by gcc. They were replaced by fbc in the emitted C file.
A deltarho/dodicat production.
Rnd6.bas
Code: Select all
#Include Once "windows.bi"
#Inclib "bcrypt"
#Include Once "win/wincrypt.bi"
Dim Shared As BCRYPT_ALG_HANDLE ptr hRand
Function Rnd6() As Double
Static As Uint32 count
Static As Uint32 Buffer(40*1024-1)
If count = 0 then BCryptGenRandom(hRand, Cast(Puchar, @Buffer(0)), 40*1024*4, 0)
Function = Buffer(count)/2^32
count += 1
If count = 40*1024-1 Then count = 0
End Function
Sub Rnd6Buffer( a() As UInt8, BufferSize as UInt32 )
redim a(0 to BufferSize - 1) as UInt8
BCryptGenRandom(hRand, @a(0), BufferSize, 0)
End Sub
' Long range
Function Rnd6range Overload( First As Int32, Last As Int32 ) As Int32
Static As Uint32 count
Static As Uint32 Buffer(40*1024-1)
If count = 0 then BCryptGenRandom(hRand, Cast(Puchar, @Buffer(0)), 40*1024*4, 0)
Function = CLng( Buffer(count) Mod (Last-First+1)) + First ' Mod by dodicat
count += 1
If count = 40*1024-1 Then count = 0
End Function
' Floating point range
Function Rnd6range Overload( First As Double, Last As Double ) As Double
Static As Uint32 count
Static As Uint32 Buffer(40*1024-1)
If count = 0 then BCryptGenRandom(hRand, Cast(Puchar, @Buffer(0)), 40*1024*4, 0)
Function = Buffer(count)/2^32 * ( Last - First ) + First
count += 1
If count = 40*1024-1 Then count = 0
End Function
Sub on_init( ) Constructor
BCryptOpenAlgorithmProvider(@hRand, BCRYPT_RNG_ALGORITHM, 0, 0)
End Sub
Sub on_exit( ) Destructor
If hRand Then BCryptCloseAlgorithmProvider(hRand, 0)
End Sub