Random number generators ( MWC256 & CMWC4096 )
Posted: Wed Feb 22, 2012 4:12 pm
mwc256.pbi :
Code: Select all
; *********************************************
; * A PureBasic version of the *
; * *
; * MWC256 PRNG algorithm by George Marsaglia *
; * (period = 2^8222) *
; * *
; *********************************************
Macro m_mwc256
!mov eax, 809430660
!movzx ecx, byte [mwc256index]
!inc cl
!mov dword [mwc256index], ecx
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
!mul dword [mwc256state + ecx * 4]
!add eax, dword [mwc256carry]
!adc edx, 0
!mov dword [mwc256state + ecx * 4], eax
CompilerElse
!lea r8, [mwc256state]
!mul dword [r8 + rcx * 4]
!add eax, dword [mwc256carry]
!adc edx, 0
!mov dword [r8 + rcx * 4], eax
CompilerEndIf
!mov dword [mwc256carry], edx
EndMacro
DataSection
!mwc256state: times 256 dd 0
!mwc256carry: dd 362436
!mwc256index: dd 255
EndDataSection
; *** mwc256seed(seed.l) ***
Procedure mwc256seed(seed.l)
EnableASM
MOV eax, seed
DisableASM
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
!lea r8, [mwc256state]
CompilerEndIf
!mov dword [mwc256state], eax
!mov ecx, 1
!mwc256seed_loop:
!mov edx, eax
!shr edx, 30
!xor eax, edx
!mov edx, 1812433253
!mul edx
!add eax, ecx
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
!mov dword [mwc256state + ecx * 4], eax
CompilerElse
!mov dword [r8 + rcx * 4], eax
CompilerEndIf
!inc cl
!jnz mwc256seed_loop
!xor edx, edx
!mov ecx, 61137367
!div ecx
!mov dword [mwc256carry], edx
!mov dword [mwc256index], 255
EndProcedure
mwc256seed(Date())
; *** mwc256() - get random long ***
Procedure mwc256()
m_mwc256
ProcedureReturn
EndProcedure
; *** mwc256range(min.l, max.l) - random [min - max] ***
; requirements : min >= 0, max <= 2147483647, min < max
Procedure mwc256range(min.l, max.l)
m_mwc256
EnableASM
MOV ecx, min
MOV edx, max
DisableASM
!sub edx, ecx
!inc edx
!mul edx
!mov eax, edx
!add eax, ecx
ProcedureReturn
EndProcedure
; *** mwc256f() - get random float [0 - 1) ***
Procedure.f mwc256f()
Static result.f
m_mwc256
!movd xmm0, eax
!psrlq xmm0, 9
!mov eax, 1
!cvtsi2ss xmm1, eax
!por xmm0, xmm1
!subss xmm0, xmm1
!movd [s_mwc256f.v_result], xmm0
ProcedureReturn result
EndProcedure
; *** mwc256d() - get random double [0 - 1) ***
Procedure.d mwc256d()
Static result.d
m_mwc256
!movd xmm0, eax
m_mwc256
!movd xmm1, eax
!punpckldq xmm0, xmm1
!psrlq xmm0, 12
!mov eax, 1
!cvtsi2sd xmm1, eax
!por xmm0, xmm1
!subsd xmm0, xmm1
!movq [s_mwc256d.v_result], xmm0
ProcedureReturn result
EndProcedure