About Monkey 2 › Forums › Monkey 2 Programming Help › trying to implement Mersenne Twister
This topic contains 6 replies, has 4 voices, and was last updated by 
 kanati 8 months, 2 weeks ago.
- 
		AuthorPosts
 - 
		
			
				
December 7, 2016 at 1:38 pm #5635
I want a repeatable sequence of numbers to do procedurally generated levels (I want to be sure of the same sequence regardless of OS or hardware)
I’ve attempted to implement https://en.wikipedia.org/wiki/Mersenne_Twister but seem to be getting four distinct bands of values when I plot 1000 values in a spreadsheet
anyone got any ideas what I’m doing wrong?
[/crayon]Monkey123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566[crayon-5cb9b3aad1250814286441 inline="true" ]'https://en.wikipedia.org/wiki/Mersenne_TwisterClass MT19937Method New(seed:uint)oldSeed = seedreset()End MethodMethod get:uint()If index >= 624 Then twist()Local y:UInt = mt[index]y = y ~ y Shr 11y = y ~ y Shl 7 & 2636928640y = y ~ y Shl 15 & 4022730752y = y ~ y Shr 18index = index + 1Return mask(y)End MethodMethod reset()index = 624mt[0] = oldSeedFor Local i:Int = 1 To 624mt[i] = mask(1812433253 * (mt[i-1] ~ mt[i-1] Shr 30) + i)NextEnd MethodPrivateField oldSeed:shortField index:intField mt:UInt[] = New uint[624]Method mask:uint(x:UInt)Return $FFFFFFFF & xEnd MethodMethod twist()Local y:uintFor Local i:Int = 0 To 624y =mask( (mt[i] & $80000000) + (mt[(i+1) Mod 624] & $7fffffff) )mt[i] = mask( mt[(i + 397) Mod 624] ~ y Shr 1 )If (y Mod 2) <> 0 Then mt[i] = mt[i] ~ $9908b0dfNextindex = 0End MethodEnd ClassFunction Main()Local mt:MT19937 = New MT19937(12345678)#RemFor Local i:Int = 0 To 32Print mt.get()NextPrint "------"mt.reset()#end remFor Local i:Int = 0 To 1024Print mt.get()NextEnd FunctionDecember 7, 2016 at 1:49 pm #5636Eeeks. That kind of bit shifting is so ugly..
With a fast look I see that oldseed is sometimes a short and sometimes a uint.. Is it normal?
In that kind of code we are supposed to see only unsigned things don’t we? (index i signed too)December 7, 2016 at 3:47 pm #5638ack I was trying it as short must have missed one, sadly that makes no difference to this issue I described? the index type doesn’t seem to be causing the issue either….
out of interest why is bitshifting ugly?
December 7, 2016 at 3:59 pm #5639BINGO!
basically it was an issue with the order of precidence of operations, obviously things are evaluated differently to C / python….
[/crayon]Monkey1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768[crayon-5cb9b3aada192866616717 inline="true" ]'https://en.wikipedia.org/wiki/Mersenne_TwisterClass MT19937Method New(seed:uint)oldSeed = seedreset()End MethodMethod get:uint()If index >= 624 Then twist()Local y:UInt = mt[index]y = y ~ (y Shr 11)y = y ~ ((y Shl 7) & 2636928640)y = y ~ ((y Shl 15) & 4022730752)y = y ~ (y Shr 18)index = index + 1Return mask(y)End MethodMethod reset()index = 624mt[0] = oldSeedFor Local i:Int = 1 To 624mt[i] = mask(1812433253 * (mt[i-1] ~ (mt[i-1] Shr 30)) + i)NextEnd MethodPrivateField oldSeed:UIntField index:UIntField mt:UInt[] = New uint[625]Method mask:uint(x:UInt)Return $FFFFFFFF & xEnd MethodMethod twist()Local y:UIntFor Local i:Int = 0 To 624y =mask( (mt[i] & $80000000) + (mt[(i+1) Mod 624] & $7fffffff) )mt[i] = mask( mt[(i + 397) Mod 624] ~ y Shr 1 )If (y Mod 2) <> 0 Then mt[i] = mt[i] ~ $9908b0dfNextindex = 0End MethodEnd ClassFunction Main()Local mt:MT19937 = New MT19937(123)#RemFor Local i:Int = 0 To 32Print mt.get()NextPrint "------"mt.reset()#end remFor Local i:Int = 0 To 1024Print mt.get()NextEnd FunctionAugust 6, 2018 at 8:28 pm #15257Ah this brings back memories. Wrote the twister into a dll for use with B+ and BMax back in the day because both created a different set depending on which CPU architecture you had (Well, on certain intels and certain AMDs they did). Glad to see someone else decided to implement it in Monkey so I don’t have to.
August 6, 2018 at 9:47 pm #15258Ooh this is really important for procedural generation in games and getting consistent results from a seed. How is the performance using this is it a ton slower than just rand or not too bad?
August 6, 2018 at 10:33 pm #15259I haven’t tried codifies implementation of it but I wouldn’t imagine it to be significantly slower than the built in PRNG. I know when I implemented it for blitzplus and blitzmax I saw no performance hit at all. Though I will admit that I didn’t stress test it against Mark’s PRNG. But it definitely gave consistent results across platforms.
 - 
		AuthorPosts
 
You must be logged in to reply to this topic.