#!/usr/bin/ruby

# Implementation of a variation of the Mersenne Twister (unbounded).
# Returns a random float in the interval [0, 1)
# See: https://en.wikipedia.org/wiki/Mersenne_Twister

class MT19937(seed, prec = 32) {

    has l = 18
    has a = 0x9908B0DF
    has f = 1812433253

    has (u, d) = (11, 1<<prec - 1)
    has (s, b) = (7, 0x9D2C5680)
    has (t, c) = (15, 0xEFC60000)
    has (n, m) = (624, 397)

    has mt = [0]*n

    has index = n+1
    has decimals = 10**prec

    method init {

        index = n
        mt[0] = seed

        for i in ^(n-1) {
            mt[i+1] =(f * (mt[i] ^ (mt[i] >> prec)) + i+1)
        }
    }

    method extract_number {
        if (index >= n) {
            if (index > n) {
                die "Generator was never seeded";
            }
            self.twist
        }

        var y = mt[index]
        y = (y ^ ((y >> u) & d))
        y = (y ^ ((y << s) & b))
        y = (y ^ ((y << t) & c))
        y = (y ^ (y >> l))

        ++index
        float((y % decimals) / decimals)
    }

    method twist {
        for i in ^n {
            var x = (mt[i] + mt[(i+1) % n])
            var xA = (x >> 1)
            if ((x % 2) != 0) {
                xA ^= a
            }
            mt[i] = (mt[(i + m) % n] ^ xA)
        }
        index = 0
    }
}

var obj = MT19937(seed: 42)
10.times {  say obj.extract_number }
