You are on page 1of 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 Private Private Private Private Private Private Private Private Private Private Private Private Private Private Private Private mt(0 To n - 1) As Currency mti As Integer mag01(0 To 1) As Currency seed_ As Currency Const Const Const Const Const Const Const Const Const Const Const Const Const MATRIX_A As Currency = 2567483615@ UPPER_MASK As Currency = 2147483648@ LOWER_MASK As Currency = 2147483647@ FULL_MASK As Currency = 4294967295@ FULL_MASK_P1 As Currency = 4294967296@ TEMPERING_MASK_B As Currency = 2636928640@ TEMPERING_MASK_C As Currency = 4022730752@ B2_7 As Currency = 128@ B2_11 As Currency = 2048@ B2_15 As Currency = 32768@ B2_18 As Currency = 262144@ B2_32 = 4294967296@ 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-

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 mti End Sub ' This function contains the Mersenne twister algorithm for quasirandom number generation Public 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-

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 = y End 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 If End 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 If End 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-

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 If End 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 If End Function

-4-