Permalink
Browse files

Add Mersenne Twister implementation.

  • Loading branch information...
1 parent b54b119 commit 98ffa77a64cd06a1a3ac506ba0398ea7309bef49 @nolanlum committed Nov 24, 2011
Showing with 170 additions and 0 deletions.
  1. +33 −0 examples/mersenne.winxed
  2. +5 −0 setup.winxed
  3. +112 −0 src/unstable/random/MersenneTwister.winxed
  4. +20 −0 src/unstable/random/RandomNumber.winxed
View
@@ -0,0 +1,33 @@
+// Mersenne Twister example.
+
+function main[main]()
+{
+ var rosella = load_packfile("rosella/core.pbc");
+ var(Rosella.initialize_rosella)("random");
+
+ var rnd = new Rosella.Random.MersenneTwister();
+
+ print("20 random integers: ");
+ for(int i = 0; i < 20; i++)
+ {
+ print(rnd.get());
+ print(" ");
+ }
+ say("");
+
+ print("20 random floats: ");
+ for(int i = 0; i < 20; i++)
+ {
+ print(rnd.get_float());
+ print(" ");
+ }
+ say("");
+
+ print("20 random ints in [0, 10): ");
+ for(int i = 0; i < 20; i++)
+ {
+ print(rnd.get_range(0, 10));
+ print(" ");
+ }
+ say("");
+}
View
@@ -321,6 +321,11 @@ function setup_experimental_libraries(var rosella)
"commandline/Program",
"commandline/ProgramMode"
);
+
+ setup_unstable_lib(rosella, "random", [],
+ "random/RandomNumber",
+ "random/MersenneTwister"
+ );
}
function setup_utilities(var rosella)
@@ -0,0 +1,112 @@
+namespace Rosella
+{
+ namespace Random
+ {
+ class MersenneTwister : RandomNumber
+ {
+ // Period parameters
+ var N;
+ var M;
+ var MATRIX_A;
+ var UPPER_MASK;
+ var LOWER_MASK;
+
+ // Tempering paramters
+ var TEMPERING_MASK_B;
+ var TEMPERING_MASK_C;
+
+ var mt; // state vector
+ var mti; // mti == N + 1 means mt[N] is not initialized
+ var mag01;
+
+ function MersenneTwister()
+ {
+ self.N = 624;
+ self.M = 397;
+ self.MATRIX_A = 0x9908b0df;
+ self.UPPER_MASK = 0x80000000; // most significant bit
+ self.LOWER_MASK = 0x7FFFFFFF; // the rest
+
+ self.TEMPERING_MASK_B = 0x9D2C5680;
+ self.TEMPERING_MASK_C = 0xEFC60000;
+
+ self.mt = [];
+ self.mag01 = [];
+
+ int t;
+ ${ time t };
+ self.initialize(t);
+ }
+
+ function initialize(int seed)
+ {
+ self.mag01[0] = 0;
+ self.mag01[1] = self.MATRIX_A;
+
+ self.mt[0] = seed & 0xFFFFFFFF;
+ for (self.mti = 1; self.mti < self.N; self.mti++)
+ {
+ int y = self.mt[self.mti - 1];
+ int z;
+ ${ lsr z, y, 30 };
+
+ self.mt[self.mti] = 1812433253 * (self.mt[self.mti - 1] ^ z) + self.mti;
+ self.mt[self.mti] = self.mt[self.mti] & 0xFFFFFFFF;
+ }
+ }
+
+ function get()
+ {
+ int y;
+ int z;
+
+ if (self.mti >= self.N)
+ {
+ int kk;
+ var mt = self.mt;
+ var mag01 = self.mag01;
+
+ for (kk = 0; kk < self.N - self.M; kk++)
+ {
+ y = (mt[kk] & self.UPPER_MASK) | (mt[kk + 1] & self.LOWER_MASK);
+ ${ lsr z, y, 1 };
+ mt[kk] = mt[kk + self.M] ^ z ^ mag01[y & 1];
+ }
+ for (; kk < self.N - 1; kk++)
+ {
+ y = (mt[kk] & self.UPPER_MASK) | (mt[kk + 1] & self.LOWER_MASK);
+ ${ lsr z, y, 1 };
+ mt[kk] = mt[kk + (self.M - self.N)] ^ z ^ mag01[y & 1];
+ }
+
+ y = (mt[self.N - 1] & self.UPPER_MASK) | (mt[0] & self.LOWER_MASK);
+ ${ lsr z, y, 1 };
+ mt[self.N - 1] = mt[self.M - 1] ^ z ^ mag01[y & 1];
+
+ self.mti = 0;
+ }
+
+ y = self.mt[self.mti];
+ self.mti++;
+
+ ${ lsr z, y, 11 };
+ y = y ^ z; // TEMPERING_SHIFT_U(y)
+ y = y ^ (y << 7) & self.TEMPERING_MASK_B; // TEMPERING_SHIFT_S(y)
+ y = y ^ (y << 15) & self.TEMPERING_MASK_C; // TEMPERING_SHIFT_L(y)
+ ${ lsr z, y, 18 };
+ y = y ^ z; // TEMPERING_SHIFT_T(y)
+
+ return y;
+ }
+
+ function get_float()
+ {
+ float n = (1 << 24);
+ int y = self.get();
+ ${ lsr y, y, 8 };
+
+ return y / n;
+ }
+ }
+ }
+}
@@ -0,0 +1,20 @@
+class Rosella.Random.RandomNumber
+{
+ // Seed the random number generator with the given seed.
+ function initialize(int seed) { }
+
+ // Gets a random signed integer from [INT_MIN, INT_MAX].
+ function get() { }
+
+ // Gets a random floating-point number from [0, 1).
+ function get_float() { }
+
+ // Gets a random signed integer from [low, high).
+ function get_range(int low, int high)
+ {
+ float f = self.get_float();
+ int i = f * (high - low) + low;
+
+ return i;
+ }
+}

0 comments on commit 98ffa77

Please sign in to comment.