RubyでMersenneTwister(MT19937)

最近、一度習って完全に忘れかけていたRubyを再学習し始めました。

以前疑似乱数の性能についてプチ実験をした時にも出てきたメルセンヌ・ツイスタ(MT19937、配布ページhttp://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/mt.html)Rubyで書きうつしてみました。(ただし単一の整数の種による初期化と32ビット整数生成のみ実装)
本家のC製メルセンヌ・ツイスタと出力を比較して一応出力だけはあっているはずです。

ただし、オブジェクト指向言語であるRubyの特性も考慮して以下のようにしました。

・Randomクラスとして定義。
・Random.new(seed)で種seedを与えて初期化。
・Random.new(nil)の場合で初期化(本家で未初期化の場合と同じ)
・メソッドnextIntで32bit符号なし整数を得る。

以下コード

class Random
	def initialize(s)
		@N = 624
		@M = 397
		@CONST = [0,0x9908b0df]
		@MSB = 0x80000000
		@LSB = 0x7fffffff
		@i = 1
		@mt = Array.new(@N)
		if s==nil then
			@mt[0] = 5489 & 0xffffffff
		else
			@mt[0] = s & 0xffffffff
		end
		while @i<@N
			@mt[@i] = 1812433253 * (@mt[@i-1]^(@mt[@i-1]>>30)) + @i
			@mt[@i] &= 0xffffffff
			@i = @i+1
		end
	end
	
	def nextInt
		#Twisting
		if @i==@N then
			@twi=0
			while @twi < @N-@M
				@n = (@mt[@twi]&@MSB) | (@mt[@twi+1]&@LSB)
				@mt[@twi] = @mt[@twi+@M] ^ (@n>>1) ^ @CONST[@n&1]
				@twi += 1
			end
			while @twi < @N-1
				@n = (@mt[@twi]&@MSB) | (@mt[@twi+1]&@LSB)
				@mt[@twi] = @mt[@twi+@M-@N] ^ (@n>>1) ^ @CONST[@n&1]
				@twi += 1
			end
			@n = (@mt[@N-1]&@MSB) | (@mt[0]&@LSB)
			@mt[@N-1] = @mt[@M-1] ^ (@n>>1) ^ @CONST[@n&1]
			@i = 0
		end
		@i += 1
		
		#Tempering
		@n = @mt[@i-1]
		@n ^= (@n >> 11)
		@n ^= (@n << 7) & 0x9d2c5680
		@n ^= (@n << 15) & 0xefc60000
		@n ^= (@n >> 18)
		return @n&0xffffffff
	end
end

まずメルセンヌ・ツイスタのコードをじっくり読むこと自体が初めてだったんで、そこで苦労しました。なので、基本的にはほとんど書きうつしになっちゃってます。
あと、今ではより改善されたメルセンヌ・ツイスタが開発されているそうですね。
そういやそもそもRubyの疑似乱数生成器は何のアルゴリズムを使用しているのだろうか。


それではこの辺で〜(・ω・)ノシ