I will leave the code cleaning as an exercise, but it works as is.
Code: Select all
/' An implementation of the MT19937 Algorithm for the Mersenne Twister
by Evan Sultanik. Based upon the pseudocode in: M. Matsumoto and
T. Nishimura, "Mersenne Twister: A 623-dimensionally
equidistributed uniform pseudorandom number generator," ACM
Transactions on Modeling and Computer Simulation Vol. 8, No. 1,
January pp.3-30 1998.
https://github.com/ESultanik/mtwister
License Public domain. Have fun!
'/
#pragma once
#include once "crt/long.bi"
const UPPER_MASK = &h80000000
const LOWER_MASK = &h7fffffff
const TEMPERING_MASK_B = &h9d2c5680
const TEMPERING_MASK_C = &hefc60000
#define __MTWISTER_H
const STATE_VECTOR_LENGTH = 624
const STATE_VECTOR_M = 397 ' changes to STATE_VECTOR_LENGTH also require changes to this
type tagMTRand
mt(0 to 623) as culong
index as long
end type
type MTRand as tagMTRand
declare function seedRand(byval seed as culong) as MTRand
declare function genRandLong(byval rand as MTRand ptr) as culong
declare function genRand(byval rand as MTRand ptr) as double
private sub m_seedRand(byval rand as MTRand ptr, byval seed as culong)
/' set initial seeds to mt[STATE_VECTOR_LENGTH] using the generator
from Line 25 of Table 1 in: Donald Knuth, "The Art of Computer
Programming," Vol. 2 (2nd Ed.) pp.102.
'/
dim as long i
rand->mt(0) = seed and &hffffffff
For i = 1 To STATE_VECTOR_LENGTH - 1
rand->mt(i) = (6069 * rand->mt((i - 1))) and &hffffffff
next
rand->index=i
end sub
/'
Creates a new random number generator from a given seed.
'/
private function seedRand(byval seed as culong) as MTRand
dim rand as MTRand
m_seedRand(@rand, seed)
return rand
end function
/'
Generates a pseudo-randomly generated long.
'/
private function genRandLong(byval rand as MTRand ptr) as culong
dim y as culong
static mag(0 to 1) as culong = {&h0, &h9908b0df} ' mag[x] = x * 0x9908b0df for x = 0,1
if (rand->index >= 624) orelse (rand->index < 0) then
' generate STATE_VECTOR_LENGTH words at a time
dim kk as long
if (rand->index >= (624 + 1)) orelse (rand->index < 0) then
m_seedRand(rand, 4357)
end if
kk = 0
Do While kk<STATE_VECTOR_LENGTH-STATE_VECTOR_M
y = (rand->mt(kk) and &h80000000) or (rand->mt((kk + 1)) and &h7fffffff)
rand->mt(kk) = (rand->mt((kk + 397)) xor (y shr 1)) xor mag((y and &h1))
kk += 1
loop
Do While kk<STATE_VECTOR_LENGTH-1
y = (rand->mt(kk) and &h80000000) or (rand->mt((kk + 1)) and &h7fffffff)
rand->mt(kk) = (rand->mt((kk + (397 - 624))) xor (y shr 1)) xor mag((y and &h1))
kk += 1
loop
y = (rand->mt((624 - 1)) and &h80000000) or (rand->mt(0) and &h7fffffff)
rand->mt((624 - 1)) = (rand->mt((397 - 1)) xor (y shr 1)) xor mag((y and &h1))
rand->index = 0
end if
y = rand->mt(rand->index)
rand->index += 1
y xor= y shr 11
y xor= (y shl 7) and &h9d2c5680
y xor= (y shl 15) and &hefc60000
y xor= y shr 18
return y
end function
/'
Generates a pseudo-randomly generated double in the range [0..1].
'/
function genRand(byval rand as MTRand ptr) as double
return cdbl(cdbl(genRandLong((rand))) / cast(culong, &hffffffff))
end function
'' end of mtwister
'' simple test
dim as MTRand r = seedRand(1337)
for i as long=0 to 20
print genRand(@r)
next