Mersenne Twister Random Generator

new topic     » topic index » view thread      » older message » newer message

Hi,
here is an implementation of the Mersenne Twister (MT) algorithm. I'd
appreciate some people validating it. I converted it from a C program. The
tricky parts in the conversion were the bitwise operations and the
zero-based array references.

It got the C code from http://www.math.keio.ac.jp/~matumoto/emt.html and
there are other varieties there as well.

----
Derek.
--------------

-- A Euphoria program for MT19937: Real number version
-- rand_mt() generates one pseudorandom real number (double)
-- which is uniformly distributed on [0,1]-interval, for each
-- call. seedrand_mt(seed) set initial values to the working area
-- of 624 words. Before rand_mt(), seedrand_mt(seed) must be
-- called once. 'seed' is any 32-bit integer, however if 0 is supplied
-- the value of time(0) is used instead.
-- Integer generator is obtained by modifying two lines.
-- This Euphoria version is based on the 'C' version coded by
-- Takuji Nishimura, considering the suggestions by
-- Topher Cooper and Marc Rieffel in July-Aug. 1997.

-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Library General Public
-- License as published by the Free Software Foundation; either
-- version 2 of the License, or (at your option) any later
-- version.
-- This library is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-- See the GNU Library General Public License for more details.
-- You should have received a copy of the GNU Library General
-- Public License along with this library; if not, write to the
-- Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-- 02111-1307  USA

-- Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura.
-- Any feedback is very welcome. For any question, comments,
-- see http://www.math.keio.ac.jp/matumoto/emt.html or email
-- matumoto at math.keio.ac.jp

include machine.e

-- Period parameters
constant N = 624
constant M = 397
constant MATRIX_A   = #9908B0DF -- constant vector a
constant UPPER_MASK = #80000000 -- most significant w-r bits
constant LOWER_MASK = #7FFFFFFF -- least significant r bits

-- Tempering parameters
constant TEMPERING_MASK_B = #9D2C5680
constant TEMPERING_MASK_C = #EFC60000

function shift_bits(atom a, integer distance)
    sequence abits

    abits = int_to_bits(a,32)
    if distance < 0 then
        distance  = -distance
        abits[distance+1 .. 32] = abits[1 .. 32-distance]
        abits[1 .. distance] = repeat(0, distance)
    else
        abits[1 .. 32-distance] = abits[distance+1 .. 32]
        abits[32 - distance + 1 .. 32] = repeat(0, distance)
    end if

    return bits_to_int(abits)

end function

sequence mt
mt = repeat(0,N) -- the array for the state vector
integer mti
mti = N + 2 -- mti=N+2 means mt[N] is not initialized

-- initializing the array with a NONZERO seed
global procedure seedrand_mt(atom seed)
    atom temp
    -- setting initial seeds to mt[N] using
    -- the generator Line 25 of Table 1 in
    -- [KNUTH 1981, The Art of Computer Programming
    --    Vol. 2 (2nd Ed.), pp102]

    if seed = 0 then
        seed = floor(time())
    end if
    mt[1]= remainder(seed , #FFFFFFFF)
    mti = 1
    while mti < N do
        mt[mti+1] = remainder((69069 * mt[mti]),#FFFFFFFF)
        mti += 1
    end while
end procedure

sequence mag01
global function rand_mt(integer range)

    atom y
    integer kk

    mag01= {0, MATRIX_A}

    if (mti >= N) then -- generate N words at one time

        if (mti = N+2)  then -- if seedrand_mt() has not been called,
            seedrand_mt(4357) -- a default initial seed is used
        end if
        kk = 0
        while kk < N-M do
            y = or_bits(and_bits(mt[kk+1],UPPER_MASK),
                        and_bits(mt[kk+2],LOWER_MASK)
                       )

            mt[kk+1] = xor_bits(xor_bits(mt[kk+M+1] , shift_bits(y , 1)) ,
                                mag01[and_bits(y,1)+1])
            kk += 1
        end while

        while kk<N-1 do
            y = or_bits(and_bits(mt[kk+1],UPPER_MASK),
                        and_bits(mt[kk+2],LOWER_MASK)
                       )
            mt[kk+1] = xor_bits(xor_bits(mt[kk+(M-N)+1] , shift_bits(y,1)) ,
                                mag01[and_bits(y,1)+1])
            kk += 1
        end while

        y = or_bits(and_bits(mt[N],UPPER_MASK),
                    and_bits(mt[1],LOWER_MASK))
        mt[N] = xor_bits(xor_bits(mt[M] , shift_bits(y,1)) ,
                             mag01[and_bits(y,1)+1])

        mti = 0
    end if
    mti += 1
    y = mt[mti]

    y = xor_bits(y, shift_bits(y, 11))
    y = xor_bits(y,and_bits(shift_bits(y,-7), TEMPERING_MASK_B))
    y = xor_bits(y,and_bits(shift_bits(y,-15), TEMPERING_MASK_C))
    y = xor_bits(y, shift_bits(y, 18))

    return  floor((y + #80000000) * (range/#FFFFFFFF) ) + 1
end function
----------- END OF SOURCE CODE ------------

new topic     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu