For more information, check: fomu-random.org
A 'quick and dirty' FreeBASIC implementation, with a short DEMO ...
Conditions to post here (in this thread) are:
everyone, except: d..r..[...], jj... and S...F... (personae's non grata here)
Of course NOT thread-safe (for speed), thread-safe means of course, slower (more overhead) ...
No one still sane, wants un-needed overhead (slow-down)!
code:
Code: Select all
' romuTrio64_rand.bas -- (c) 2021-07-27, MrSwiss (FreeBASIC translation/implementation)
' rotate-left macro 32 & 64-bits tested
#Define ROTL(v,r) CULngInt(v) Shl (r) Or CULngInt(v) Shr (8 * SizeOf(v) - (r))
' end macro
Type romu3_t ' 64-bit PRNG (c) Mark A. Overton, https://www.romu-random.org
Private:
Const DmulF = 1d / CDbl(&hFFFFFFFFFFFFFFFFull) ' small error, negligible
As ULongInt xState, yState, zState ' 192-bit State
Public:
declare Constructor ()
Declare Constructor (ByVal As ULongInt, ByVal As ULongInt, _
ByVal As ULongInt, ByVal As UShort = 4e3)
Declare Function r_u64() As ULongInt
Declare Function r_f64() As Double
End Type
Constructor romu3_t() ' default ctor (fixed initializers: 11, 22, 33)
With This
.xState = 11 : .yState = 22 : zState = 33
For i As UInteger = 0 To 999 ' 4000 call's (warm-up)
.r_u64() : .r_u64() : .r_u64() : .r_u64()
Next
End With
End Constructor
Constructor romu3_t( _ ' copy ctor (user defined initializers)
ByVal x_ As ULongInt, _ ' mandatory
ByVal y_ As ULongInt, _ ' mandatory
ByVal z_ As ULongInt, _ ' mandatory
ByVal nrun As UShort = 4e3 _ ' optional, default 4000 call's (warm-up)
)
With This
.xState = x_ : .yState = y_ : zState = z_
For i As UInteger = 1 To nrun Shr 2 ' integer division by 4
.r_u64() : .r_u64() : .r_u64() : .r_u64()
Next
End With
End Constructor
Function romu3_t.r_u64() As ULongInt
With This
Dim As ULongInt xp = .xState, _
yp = .yState, _
zp = .zState
.xState = 15241094284759029579ull * zp
.yState = yp - xp : .yState = ROTL(.yState, 12)
.zState = zp - yp : .zState = ROTL(.zState, 44)
Return xp
End With
End Function
Function romu3_t.r_f64() As Double
Return This.r_u64() * This.DmulF
End Function
' end type
' ===== DEMO =====
Dim As romu3_t rnd1 = Type<romu3_t>(1001, 2039, 50733)
Dim As ULongInt cnt = 1
Print "running ... for 10 seconds, please wait."
Locate ,, 0
Var et = Timer + 10
While Timer < et
rnd1.r_f64 : cnt += 1
Wend
Locate ,, 1
Print : Print "running at: " + Str(CSng(cnt / 1e7)) + " MHz"
Print : Print : Print "... done ... ";
Sleep
' ===== end DEMO =====