mt19937.pdf

4
C:\Users\chanmu\Desktop\vba\kbasket\MT19937.cls Sunday, November 3, 2013 9:47 AM VERSION 1.0 CLASS BEGIN MultiUse = -1 'True END Attribute VB_Name = "MT19937" Attribute VB_GlobalNameSpace = False Attribute VB_Creatable = False Attribute VB_PredeclaredId = False Attribute VB_Exposed = False Option Explicit Option Base 0 ' The Mersenne twister pseudo random number generator. Private Declare Function GetTickCount Lib "kernel32.dll" () As Long Private Const n = 624 Private Const M = 397 Private mt(0 To n - 1) As Currency Private mti As Integer Private mag01(0 To 1) As Currency Private seed_ As Currency Private Const MATRIX_A As Currency = 2567483615@ Private Const UPPER_MASK As Currency = 2147483648@ Private Const LOWER_MASK As Currency = 2147483647@ Private Const FULL_MASK As Currency = 4294967295@ Private Const FULL_MASK_P1 As Currency = 4294967296@ Private Const TEMPERING_MASK_B As Currency = 2636928640@ Private Const TEMPERING_MASK_C As Currency = 4022730752@ Private Const B2_7 As Currency = 128@ Private Const B2_11 As Currency = 2048@ Private Const B2_15 As Currency = 32768@ Private Const B2_18 As Currency = 262144@ Private Const B2_32 = 4294967296@ Private Const IB2_32 As Double = 1# / B2_32 Private box_muller_tmp As Double Private box_muller_bool As Boolean Private Sub Class_Initialize() mag01(0) = 0@ mag01(1) = MATRIX_A seed_ = 0@ mti = n + 1 End Sub Property Get seed() As Currency seed = seed_ End Property -1-

Upload: mk3chan

Post on 01-Jan-2016

4 views

Category:

Documents


0 download

DESCRIPTION

MT19937

TRANSCRIPT

Page 1: MT19937.pdf

C:\Users\chanmu\Desktop\vba\kbasket\MT19937.cls Sunday, November 3, 2013 9:47 AM

VERSION 1.0 CLASSBEGIN MultiUse = -1 'TrueENDAttribute VB_Name = "MT19937"Attribute VB_GlobalNameSpace = FalseAttribute VB_Creatable = FalseAttribute VB_PredeclaredId = FalseAttribute VB_Exposed = FalseOption ExplicitOption Base 0

' The Mersenne twister pseudo random number generator.

Private Declare Function GetTickCount Lib "kernel32.dll" () As LongPrivate Const n = 624Private Const M = 397

Private mt(0 To n - 1) As CurrencyPrivate mti As IntegerPrivate mag01(0 To 1) As CurrencyPrivate seed_ As Currency

Private Const MATRIX_A As Currency = 2567483615@Private Const UPPER_MASK As Currency = 2147483648@Private Const LOWER_MASK As Currency = 2147483647@Private Const FULL_MASK As Currency = 4294967295@Private Const FULL_MASK_P1 As Currency = 4294967296@Private Const TEMPERING_MASK_B As Currency = 2636928640@Private Const TEMPERING_MASK_C As Currency = 4022730752@

Private Const B2_7 As Currency = 128@Private Const B2_11 As Currency = 2048@Private Const B2_15 As Currency = 32768@Private Const B2_18 As Currency = 262144@Private Const B2_32 = 4294967296@Private Const IB2_32 As Double = 1# / B2_32

Private box_muller_tmp As DoublePrivate box_muller_bool As Boolean

Private Sub Class_Initialize() mag01(0) = 0@ mag01(1) = MATRIX_A seed_ = 0@ mti = n + 1End Sub

Property Get seed() As Currency seed = seed_End Property

-1-

Page 2: MT19937.pdf

C:\Users\chanmu\Desktop\vba\kbasket\MT19937.cls Sunday, November 3, 2013 9:47 AM

' Continous uniform distribution RNG' This function returns random numbers from a continous uniform distribution'Public Function unifrnd(Optional a As Double = 0#, Optional B As Double = 1#) As Double Dim a2 As Double, b2 As Double, mu As Double, sigma As Double unifrnd = CDbl((Twister() + 0.5)) * IB2_32 a2 = a / 2# b2 = B / 2# mu = a2 + b2 sigma = b2 - a2 unifrnd = mu + sigma * (2# * unifrnd - 1#)End Function

' The pseudorandom generator is inititalized in this code.' The seed is produce by the system clock in case it is zero.

Public Sub init_RNG(Optional seed As Currency = 0@) If seed = 0 Then seed = GetTickCount End If seed_ = seed mt(0) = func_ul32bit(seed_) For mti = 1 To n - 1 mt(mti) = func_ul32bit(69069@ * mt(mti - 1)) Next mtiEnd Sub

' This function contains the Mersenne twister algorithm for quasirandom number generationPublic Function Twister() As Currency Dim y As Currency, kk As Integer, tmp As Currency If mti >= n Then If mti = n + 1 Then init_RNG seed_ End If For kk = 0 To (n - M) - 1 y = func_or(func_u32bit(mt(kk)), func_l32bit(mt(kk + 1))) mt(kk) = func_xor(func_xor(mt(kk + M), Int(y / 2@)), mag01(func_and(y, 1))) Next kk For kk = kk To (n - 1) - 1 y = func_or(func_u32bit(mt(kk)), func_l32bit(mt(kk + 1))) mt(kk) = func_xor(func_xor(mt(kk + (M - n)), Int(y / 2@)), mag01(func_and(y, 1))) Next kk y = func_or(func_u32bit(mt(n - 1)), func_l32bit(mt(0))) mt(n - 1) = func_xor(func_xor(mt(M - 1), Int(y / 2@)), mag01(func_and(y, 1))) mti = 0 End If y = mt(mti) mti = mti + 1 y = func_xor(y, TEMPERING_SHIFT_U(y)) tmp = func_and(TEMPERING_SHIFT_S(y), TEMPERING_MASK_B) y = func_xor(y, tmp) tmp = func_and(TEMPERING_SHIFT_T(y), TEMPERING_MASK_C)

-2-

Page 3: MT19937.pdf

C:\Users\chanmu\Desktop\vba\kbasket\MT19937.cls Sunday, November 3, 2013 9:47 AM

y = func_xor(y, tmp) y = func_xor(y, TEMPERING_SHIFT_L(y)) Twister = yEnd Function

Private Function TEMPERING_SHIFT_U(y As Currency) As Currency TEMPERING_SHIFT_U = func_and(Int(y / B2_11), FULL_MASK)End Function

Private Function TEMPERING_SHIFT_S(y As Currency) As Currency TEMPERING_SHIFT_S = func_ul32bit(Int(y / B2_7))End Function

Private Function TEMPERING_SHIFT_T(y As Currency) As Currency TEMPERING_SHIFT_T = func_ul32bit(Int(y / B2_15))End Function

Private Function TEMPERING_SHIFT_L(y As Currency) As Currency TEMPERING_SHIFT_L = func_and(Int(y / B2_18), FULL_MASK)End Function

Private Function func_and(c1 As Currency, c2 As Currency) As Currency If (c1 < UPPER_MASK) And (c2 < UPPER_MASK) Then func_and = c1 And c2 End If If (c1 < UPPER_MASK) And (c2 >= UPPER_MASK) Then func_and = c1 And (c2 - UPPER_MASK) End If If (c1 >= UPPER_MASK) And (c2 < UPPER_MASK) Then func_and = (c1 - UPPER_MASK) And c2 End If If (c1 >= UPPER_MASK) And (c2 >= UPPER_MASK) Then func_and = ((c1 - UPPER_MASK) And (c2 - UPPER_MASK)) + UPPER_MASK End IfEnd Function

Private Function func_or(c1 As Currency, c2 As Currency) If (c1 < UPPER_MASK) And (c2 < UPPER_MASK) Then func_or = c1 Or c2 End If If (c1 < UPPER_MASK) And (c2 >= UPPER_MASK) Then func_or = (c1 Or (c2 - UPPER_MASK)) + UPPER_MASK End If If (c1 >= UPPER_MASK) And (c2 < UPPER_MASK) Then func_or = ((c1 - UPPER_MASK) Or c2) + UPPER_MASK End If If (c1 >= UPPER_MASK) And (c2 >= UPPER_MASK) Then func_or = ((c1 - UPPER_MASK) Or (c2 - UPPER_MASK)) + UPPER_MASK End IfEnd Function

Private Function func_xor(c1 As Currency, c2 As Currency) If (c1 < UPPER_MASK) And (c2 < UPPER_MASK) Then func_xor = c1 Xor c2

-3-

Page 4: MT19937.pdf

C:\Users\chanmu\Desktop\vba\kbasket\MT19937.cls Sunday, November 3, 2013 9:47 AM

End If If (c1 < UPPER_MASK) And (c2 >= UPPER_MASK) Then func_xor = (c1 Xor (c2 - UPPER_MASK)) + UPPER_MASK End If If (c1 >= UPPER_MASK) And (c2 < UPPER_MASK) Then func_xor = ((c1 - UPPER_MASK) Xor c2) + UPPER_MASK End If If (c1 >= UPPER_MASK) And (c2 >= UPPER_MASK) Then func_xor = (c1 - UPPER_MASK) Xor (c2 - UPPER_MASK) End IfEnd Function

Private Function func_l32bit(c1 As Currency) As Currency func_l32bit = c1 - UPPER_MASK * Int(c1 / UPPER_MASK)End Function

Private Function func_ul32bit(c1 As Currency) As Currency func_ul32bit = c1 - FULL_MASK_P1 * Int(c1 / FULL_MASK_P1)End Function

Private Function func_u32bit(c1 As Currency) As Currency If c1 > LOWER_MASK Then func_u32bit = UPPER_MASK Else func_u32bit = 0 End IfEnd Function

-4-