Skip to content
This repository has been archived by the owner on Feb 2, 2023. It is now read-only.

Commit

Permalink
Implemented TinyMT generator
Browse files Browse the repository at this point in the history
  • Loading branch information
Malachi Griffie committed Dec 8, 2013
1 parent 9939522 commit aa06f26
Show file tree
Hide file tree
Showing 8 changed files with 299 additions and 43 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.9.2
0.10.1
12 changes: 1 addition & 11 deletions src/nexus/math/LehmerGenerator.as
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,24 @@ public final class LehmerGenerator implements ISeededPRNG
private var m_currentState:uint;
private var m_numbersGenerated:int;

public function LehmerGenerator(seed:int=1)
public function LehmerGenerator(seed:uint=1)
{
this.seed = seed;
}

[Inline]
public final function get seed():uint { return m_seed; }
public final function set seed(value:uint):void
{
//if(value > 0 && value < 2147483647)
//{
m_seed = value;
m_currentState = m_seed;
m_numbersGenerated = 0;
//}
//else
//{
//throw new ArgumentError("Seed must be between 0 and 2147483647");
//}
}

[Inline]
public final function get currentState():uint { return m_currentState; }

[Inline]
public function get period():uint { return 2147483647 /*int.MAX_VALUE*/; }

[Inline]
public final function get numbersGenerated():int { return m_numbersGenerated; }

public function next():uint
Expand Down
1 change: 0 additions & 1 deletion src/nexus/math/NativeRandomGenerator.as
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ public final class NativeRandomGenerator implements IPRNG
[Inline]
public function get period():uint { return 2147483647 /*int.MAX_VALUE*/; }

[Inline]
public final function get currentState():uint { return m_currentState; }

public function next():uint
Expand Down
67 changes: 48 additions & 19 deletions src/nexus/math/Random.as
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ public class Random
// CLASS CONSTANTS
//--------------------------------------

private static const s_random : Random = new Random(new NativeRandomGenerator());
private static const s_random:Random = new Random(new NativeRandomGenerator());

public static function get instance():Random
{
return s_random;
Expand All @@ -28,7 +29,7 @@ public class Random
// INSTANCE VARIABLES
//--------------------------------------

private var m_generator : IPRNG;
private var m_generator:IPRNG;

//--------------------------------------
// CONSTRUCTOR
Expand All @@ -48,37 +49,51 @@ public class Random
//--------------------------------------

/**
* Generates a random floating point in the range [min, max).
* Generates a random floating point in the range [min, max) which is [0, 1) if neither
* argument is given.
*
* If max is NaN, Infinity, or -Infinity, a number in the range [min, 1) is returned
* If min is NaN, Infinity, or -Infinity, a number in the range [0, max) is returned
* @param min The lowest value to return, inclusive
* @param max The highest value to return, exclusive
* @return A number in the range [min, max)
*/
public function float( min : Number = NaN, max : Number = NaN ) : Number
public function float(min:Number = NaN, max:Number = NaN):Number
{
min = isNaN(min) || !isFinite(min) ? 0 : min;
max = isNaN(max) || !isFinite(max) ? 1 : max;
return ((m_generator.next() / m_generator.period) * (max - min)) + min;
var p:Number = m_generator.next() / m_generator.period;
return (p * (max - min)) + min;
}

/**
* Generates a random integer in the range [min, max]
* Generates a random integer in the range [min, max)
* @param min The lowest value to return, inclusive
* @param max The highest value to return, inclusive
* @return A number in the range [min, max]
* @param max The highest value to return, exclusive
* @return An int in the range [min, max)
*/
public function integer(min:uint = 0, max:int = int.MAX_VALUE):int
{
return m_generator.next() % (max - min) + min;
}

/**
* Generates a random unsigned integer in the range [min, max)
* @param min The lowest value to return, inclusive
* @param max The highest value to return, exclusive
* @return A uint in the range [min, max)
*/
public function integer( min : int = 1, max : int = int.MAX_VALUE ) : int
public function unsignedInteger(min:uint = 0, max:uint = uint.MAX_VALUE):uint
{
return Math.floor((m_generator.next() / m_generator.period) * (max - min + 1)) + min;
return m_generator.next() % (max - min) + min;
}

/**
* Returns a random true/false value, with a 50% chance of either
*/
public function boolean() : Boolean
public function boolean():Boolean
{
return (m_generator.next() / m_generator.period) < 0.5;
return(m_generator.next() / m_generator.period) < 0.5;
}

/**
Expand All @@ -88,10 +103,10 @@ public class Random
* @example <code>randomRound(4.3)</code> should return 4 70% of the time
* and 5 30% of the time.
*/
public function weightedRound( value : Number ) : int
public function weightedRound(value:Number):int
{
var floor : int = Math.floor(value);
return (m_generator.next() / m_generator.period) > (value - floor) ? floor : floor + 1;
var floor:int = Math.floor(value);
return(m_generator.next() / m_generator.period) > (value - floor) ? floor : floor + 1;
}

/**
Expand All @@ -100,9 +115,9 @@ public class Random
* is assumed to be a Vector or Array (or otherwise have a <code>length</code> property and
* be able to be accessed with the index operators).
*/
public function choice(...items):Object
public function choice(... items):Object
{
var choice : int;
var choice:int;
if(items.length == 1)
{
choice = integer(0, items[0].length - 1);
Expand All @@ -115,11 +130,25 @@ public class Random
}
}

public function toString(verbose:Boolean=false):String
/**
* Destructively shuffles the container using the Fisher-Yates algorithm.
*/
public function shuffle(container:Object):void
{
return "[Random" + m_generator + "]";
for(var x:int = container.length - 1; x > 0; x--)
{
var j:int = integer(0, x + 1);
var tmp:* = container[x];
container[x] = container[j];
container[j] = tmp;
}
}

public function toString(verbose:Boolean = false):String
{
return "[Random" + m_generator + "]";
}

//--------------------------------------
// PRIVATE & PROTECTED INSTANCE METHODS
//--------------------------------------
Expand Down
130 changes: 130 additions & 0 deletions src/nexus/math/TinyMersenneTwisterGenerator.as
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// Copyright (c) 2013 Robert Zubek and SomaSim LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package nexus.math
{

import flash.utils.*;

/**
* Actionscript port of the TinyMT random number generator, a small-footprint
* variant of the Mersenne Twister.
*
* <p> Original algorithm by Mutsuo Saito and Makoto Matsumoto.
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/TINYMT/index.html
*/
public class TinyMersenneTwisterGenerator implements ISeededPRNG
{
// initialization constants (in the MT reference implementation
// they're specified by the user during initialization, but they don't change)
private static const MAT1:uint = 0x70707070;
private static const MAT2:uint = 0x07070707;
private static const TMAT:uint = 0x55555555;

protected static const MIN_LOOP:int = 8;
protected static const PRE_LOOP:int = 8;

private var m_seed:uint;
private var m_currentState:uint;
private var m_numbersGenerated:int;

public function TinyMersenneTwisterGenerator(seed:uint = 1)
{
this.seed = seed;
}

public final function get seed():uint { return m_seed; }
public final function set seed(value:uint):void
{
m_seed = value;
m_currentState = m_seed;
m_numbersGenerated = 0;

stateVars[0] = m_seed;
stateVars[1] = MAT1;
stateVars[2] = MAT2;
stateVars[3] = TMAT;

for(var i:int = 1; i < MIN_LOOP; i++)
{
stateVars[i & 3] ^= i + 1812433253 * (stateVars[(i - 1) & 3] ^ (stateVars[(i - 1) & 3] >>> 30));
}

for(var j:int = 0; j < PRE_LOOP; j++)
{
nextState();
}
}

public final function get currentState():uint { return m_currentState; }

[Inline]
public function get period():uint { return 4294967295; }

public final function get numbersGenerated():int
{
return m_numbersGenerated;
}

public function next():uint
{
nextState();
return temper();
}

// state variables
private const stateVars:Vector.<uint> = new Vector.<uint>(4, true);

/**
* Advances internal state
*/
[Inline]
private final function nextState():void
{
var x:uint;
var y:uint;

y = stateVars[3];
x = (stateVars[0] & 0x7fffffff) ^ stateVars[1] ^ stateVars[2];
x ^= (x << 1);
y ^= (y >>> 1) ^ x;
stateVars[0] = stateVars[1];
stateVars[1] = stateVars[2];
stateVars[2] = x ^ (y << 10);
stateVars[3] = y;
stateVars[1] ^= -(y & 1) & MAT1;
stateVars[2] ^= -(y & 1) & MAT2;

m_numbersGenerated++;
}

/**
* Outputs an unsigned int from the current internal stats
*/
[Inline]
private final function temper():uint
{
var t0:uint = stateVars[3];
var t1:uint = stateVars[0] ^ (stateVars[2] >>> 8);
t0 ^= t1;
t0 ^= -(t1 & 1) & TMAT;
return t0;
}
}

}
1 change: 1 addition & 0 deletions test/src/MainTestSuite.as
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class MainTestSuite
public var json : JsonSerializerTest;

public var rngLehmer : LehmerGeneratorTest;
public var rngTinymt : TinyMTGeneratorTest;
public var rngNative : NativeRandomGeneratorTest;

public var hmac : HMACTest;
Expand Down
Loading

0 comments on commit aa06f26

Please sign in to comment.