diff --git a/src/nexus/IDisposable.as b/src/nexus/IDisposable.as new file mode 100644 index 0000000..fd62501 --- /dev/null +++ b/src/nexus/IDisposable.as @@ -0,0 +1,21 @@ +// Copyright 2012 Malachi Griffie +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +package nexus +{ + +/** + * Use the Dispose method of this interface to explicitly release unmanaged resources in conjunction with + * the garbage collector. The consumer of an object can call this method when the object is no longer needed. + */ +public interface IDisposable +{ + /** + * Performs tasks associated with freeing, releasing, or resetting unmanaged resources. + */ + function dispose():void; +} + +} \ No newline at end of file diff --git a/src/nexus/math/IPRNG.as b/src/nexus/math/IPRNG.as new file mode 100644 index 0000000..30e7dfd --- /dev/null +++ b/src/nexus/math/IPRNG.as @@ -0,0 +1,21 @@ +// Copyright 2012 Malachi Griffie +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +package nexus.math +{ + +/** + * ... + */ +public interface IPRNG +{ + function get currentState():uint; + + function get period():uint; + + function next():uint; +} + +} \ No newline at end of file diff --git a/src/nexus/math/ISeededPRNG.as b/src/nexus/math/ISeededPRNG.as new file mode 100644 index 0000000..c8af2af --- /dev/null +++ b/src/nexus/math/ISeededPRNG.as @@ -0,0 +1,18 @@ +// Copyright 2012 Malachi Griffie +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +package nexus.math +{ + +/** + * ... + */ +public interface ISeededPRNG extends IPRNG +{ + function get seed():uint; + function set seed(value:uint):void; +} + +} \ No newline at end of file diff --git a/src/nexus/math/LehmerGenerator.as b/src/nexus/math/LehmerGenerator.as new file mode 100644 index 0000000..8503c35 --- /dev/null +++ b/src/nexus/math/LehmerGenerator.as @@ -0,0 +1,58 @@ +// Copyright 2012 Malachi Griffie +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +package nexus.math +{ + +import flash.utils.*; + +/** + * Variant on Linear Congruential Generator. + * @see http://en.wikipedia.org/wiki/Lehmer_random_number_generator + */ +public final class LehmerGenerator implements ISeededPRNG +{ + private var m_seed:uint; + private var m_currentState:uint; + private var m_numbersGenerated:int; + + public function LehmerGenerator(seed:int=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 + { + ++m_numbersGenerated; + return m_currentState = ((m_currentState * 16807) % 2147483647); + //return m_state = ((m_state * 279470273) % 4294967291); + } +} +} \ No newline at end of file diff --git a/src/nexus/math/NativeRandomGenerator.as b/src/nexus/math/NativeRandomGenerator.as new file mode 100644 index 0000000..1c6804b --- /dev/null +++ b/src/nexus/math/NativeRandomGenerator.as @@ -0,0 +1,34 @@ +// Copyright 2012 Malachi Griffie +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +package nexus.math +{ + +import flash.utils.*; + +/** + * Random number generator using the built-in Math.random() function + */ +public final class NativeRandomGenerator implements IPRNG +{ + private var m_currentState:uint; + + public function NativeRandomGenerator() + { + + } + + [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 + { + return m_currentState = Math.random() * 2147483647; + } +} +} \ No newline at end of file diff --git a/src/nexus/math/Random.as b/src/nexus/math/Random.as new file mode 100644 index 0000000..c35a09f --- /dev/null +++ b/src/nexus/math/Random.as @@ -0,0 +1,128 @@ +// Copyright 2012 Malachi Griffie +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +package nexus.math +{ + +import flash.utils.*; + +/** + * Given a random number generator, this class provides convenience methods for + * random number generation and other random operations. + */ +public class Random +{ + //-------------------------------------- + // CLASS CONSTANTS + //-------------------------------------- + + private static const s_random : Random = new Random(new NativeRandomGenerator()); + public static function get instance():Random + { + return s_random; + } + + //-------------------------------------- + // INSTANCE VARIABLES + //-------------------------------------- + + private var m_generator : IPRNG; + + //-------------------------------------- + // CONSTRUCTOR + //-------------------------------------- + + public function Random(generator:IPRNG) + { + m_generator = generator; + } + + //-------------------------------------- + // GETTER/SETTERS + //-------------------------------------- + + //-------------------------------------- + // PUBLIC INSTANCE METHODS + //-------------------------------------- + + /** + * Generates a random floating point in the range [min, max). + * 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 + { + min = isNaN(min) || !isFinite(min) ? 0 : min; + max = isNaN(max) || !isFinite(max) ? 1 : max; + return ((m_generator.next() / m_generator.period) * (max - min)) + min; + } + + /** + * 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] + */ + public function integer( min : int = 1, max : int = int.MAX_VALUE ) : int + { + return Math.floor((m_generator.next() / m_generator.period) * (max - min + 1)) + min; + } + + /** + * Returns a random true/false value, with a 50% chance of either + */ + public function boolean() : Boolean + { + return (m_generator.next() / m_generator.period) < 0.5; + } + + /** + * Given a floating-point value, return either the value's floor or its ceiling + * chosen randomly according to whether the value is closer to the floor or + * the ceiling. + * @example randomRound(4.3) should return 4 70% of the time + * and 5 30% of the time. + */ + public function weightedRound( value : Number ) : int + { + var floor : int = Math.floor(value); + return (m_generator.next() / m_generator.period) > (value - floor) ? floor : floor + 1; + } + + /** + * Returns one of the items passed in at random. + * @param items A vararg list of objects to choose from. If a single argument is passed, it + * is assumed to be a Vector or Array (or otherwise have a length property and + * be able to be accessed with the index operators). + */ + public function choice(...items):Object + { + var choice : int; + if(items.length == 1) + { + choice = integer(0, items[0].length - 1); + return items[0][choice]; + } + else + { + choice = integer(0, items.length - 1); + return items[choice]; + } + } + + public function toString(verbose:Boolean=false):String + { + return "[Random" + m_generator + "]"; + } + + //-------------------------------------- + // PRIVATE & PROTECTED INSTANCE METHODS + //-------------------------------------- +} + +} \ No newline at end of file diff --git a/src/nexus/security/crypto/SHA1HashFunction.as b/src/nexus/security/crypto/SHA1HashFunction.as index 135b60e..662fb41 100644 --- a/src/nexus/security/crypto/SHA1HashFunction.as +++ b/src/nexus/security/crypto/SHA1HashFunction.as @@ -28,7 +28,6 @@ public class SHA1HashFunction implements IHashFunction */ public function hash(bytes:ByteArray):ByteArray { - //would be really nice if the blooddy lib just returned a damn byte array return ByteUtils.hexToBytes(SHA1.hashBytes(bytes)); } diff --git a/src/nexus/utils/Parse.as b/src/nexus/utils/Parse.as index 5a2ae92..a518f97 100644 --- a/src/nexus/utils/Parse.as +++ b/src/nexus/utils/Parse.as @@ -1,5 +1,5 @@ // Copyright 2011 Malachi Griffie -// +// // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -11,7 +11,7 @@ import flash.utils.Dictionary; /** * ... - * + * */ public class Parse { @@ -25,9 +25,9 @@ public class Parse * @param defaultValue The default value to use if the parsed Number is NaN or Infinity * @return */ - public static function number(source:*, defaultValue:Number):Number + public static function number(source:Object, defaultValue:Number):Number { - var result : Number = parseFloat(source); + var result:Number = parseFloat(source + ""); return isNaN(result) || !isFinite(result) ? defaultValue : result; } @@ -37,21 +37,21 @@ public class Parse * @param defaultValue * @return */ - public static function integer(source:*, defaultValue:int, radix:int=10):int + public static function integer(source:Object, defaultValue:int, radix:int = 10):int { //malachi: parse int returns a number which we use to check for NaN before setting to default value, if //result was of type int than NaN would result in 0 and we wouldn't be able to check and assign default value - var result : Number = parseInt(source, radix); + var result:Number = parseInt(source + "", radix); return isNaN(result) || !isFinite(result) ? defaultValue : result; } /** - * Parses a string value, the default value is used if the source is null or undefined + * Parses a string value, the default value is used if the source is null * @return */ - public static function string(source:*, defaultValue:String):String + public static function string(source:Object, defaultValue:String):String { - return (source !== null && source !== undefined ? String(source + "") : defaultValue); + return(source !== null ? String(source + "") : defaultValue); } /** @@ -61,9 +61,9 @@ public class Parse * @param defaultY The y value to use if the parsed value is NaN or Infinity * @return */ - public static function point(source:*, defaultX:int, defaultY:int):Point + public static function point(source:Object, defaultX:int, defaultY:int):Point { - var array : Array = String(source + "").split(","); + var array:Array = String(source + "").split(","); return new Point(Parse.number(array[0], defaultX), Parse.number(array[1], defaultY)); } @@ -75,10 +75,10 @@ public class Parse * @param alsoMatch If provided, will return true if the source matches this value (case-insensitive) * @return */ - public static function boolean( source: *, defaultValue:Boolean, alsoMatch : String = null ): Boolean + public static function boolean(source:Object, defaultValue:Boolean, alsoMatch:String = null):Boolean { - var match : String = alsoMatch != null ? (alsoMatch + "").toLowerCase() : null; - var check : String = (source + "").toLowerCase(); + var match:String = alsoMatch != null ? (alsoMatch + "").toLowerCase() : null; + var check:String = (source + "").toLowerCase(); if(defaultValue) { @@ -111,11 +111,11 @@ public class Parse } /* - public static function enum(source:*, enumClass:Class, caseSensitive:Boolean=false):Enum - { - return Enum.fromString(enumClass, value, caseSensitive); - } - */ + public static function enum(source:*, enumClass:Class, caseSensitive:Boolean=false):Enum + { + return Enum.fromString(enumClass, value, caseSensitive); + } + */ /** * Parses the given value as a Dictionary using the provided delimiters to split entries and key/value pairs. If @@ -131,14 +131,14 @@ public class Parse * var dict2 : Dictionary = Parse.dictionary(str2, " ", ","); * */ - public static function dictionary(source:*, entryDelimiter:String, keyValueDelimiter:String):Dictionary + public static function dictionary(source:Object, entryDelimiter:String, keyValueDelimiter:String):Dictionary { - var result : Dictionary = new Dictionary(); + var result:Dictionary = new Dictionary(); //if nothing can be parsed from the source, then we return null instead of an empty dictionary - var valuesFound : Boolean = false; + var valuesFound:Boolean = false; - var entries : Array = (source + "").split(entryDelimiter); - for(var x : int = 0; x < entries.length; ++x) + var entries:Array = (source + "").split(entryDelimiter); + for(var x:int = 0; x < entries.length; ++x) { entries[x] = String(entries[x]).split(keyValueDelimiter); //make sure that upon splitting this entry into key/value that it has two fields and the key isn't null @@ -157,21 +157,21 @@ public class Parse * @param a_string a string formatted in a valid W3C subset of ISO 8601 * @return */ - public static function iso8601Date( a_string : String, defaultValue:Date=null ) : Date + public static function iso8601Date(a_string:String, defaultValue:Date = null):Date { - if (a_string == null || a_string == "") + if(a_string == null || a_string == "") { return defaultValue; } - var regexp : RegExp = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?)?((?:([+-])(\d{2})(?::(\d{2}))?)|Z)?$/; - var match : Array = a_string.match(regexp); + var regexp:RegExp = /^(\d{4})-(\d{2})-(\d{2})(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{1,3}))?)?)?((?:([+-])(\d{2})(?::(\d{2}))?)|Z)?$/; + var match:Array = a_string.match(regexp); //trace(a_string); - if (match == null) + if(match == null) { - return new Date(0,0); + return new Date(0, 0); } //remove full-match from resulting array @@ -180,24 +180,24 @@ public class Parse //trace(match); //months are 0-based in the Date constructor for some reason - if (match[1]) + if(match[1]) { match[1]--; } - var result : Date = new Date(match[0] || 1970, match[1] || 0, match[2] || 1, match[3] || 0, match[4] || 0, match[5] || 0, match[6] || 0); + var result:Date = new Date(match[0] || 1970, match[1] || 0, match[2] || 1, match[3] || 0, match[4] || 0, match[5] || 0, match[6] || 0); //account for timezone - var timezoneOffset : int = 0; + var timezoneOffset:int = 0; //if there was something provided for timezone - if (match[7]) + if(match[7]) { - if (match[7] != "Z") + if(match[7] != "Z") { - var hours : int = parseInt(match[9]) || 0; - var minutes : int = parseInt(match[10]) || 0; + var hours:int = parseInt(match[9]) || 0; + var minutes:int = parseInt(match[10]) || 0; timezoneOffset = (hours * 60) + minutes; - if (match[8] == '+') + if(match[8] == '+') { timezoneOffset *= -1; } @@ -208,7 +208,7 @@ public class Parse //BUG: This causes a problem the the US during the spring time change when clocks advance an hour. That hour of time has //not actually elapsed, so any time-related functions (eg, time elapsed to change state of an object) will fail - if (timezoneOffset != 0) + if(timezoneOffset != 0) { result.setTime(result.getTime() + (timezoneOffset * 60 * 1000)); } diff --git a/test/src/MainTestSuite.as b/test/src/MainTestSuite.as index 3264f30..d00141a 100644 --- a/test/src/MainTestSuite.as +++ b/test/src/MainTestSuite.as @@ -8,28 +8,30 @@ package import test.*; import test.nexus.*; +import test.nexus.math.*; import test.nexus.security.crypto.*; import test.nexus.utils.*; import test.nexus.utils.reflection.*; import test.nexus.utils.serialization.json.*; [Suite] -public class MainTestSuite// extends TestSuite +public class MainTestSuite { - public var basic : BasicTest; - public var enum : EnumTest; - public var enumSet : EnumSetTest; - public var reflection : ReflectionTest; - public var reflection_typeInfo : TypeInfoTest; - public var objectUtils : ObjectUtilsTest; - public var json : JsonSerializerTest; - public var hmac : HMACTest; + public var basic : BasicTest; - public function MainTestSuite() - { - //addTest(new ReflectionCoreTest()); - //addTest(new ReflectionTypeInfoTest()); - } + public var enum : EnumTest; + public var enumSet : EnumSetTest; + + public var reflection : ReflectionTest; + public var reflection_typeInfo : TypeInfoTest; + + public var objectUtils : ObjectUtilsTest; + public var json : JsonSerializerTest; + + public var rngLehmer : LehmerGeneratorTest; + public var rngNative : NativeRandomGeneratorTest; + + public var hmac : HMACTest; } } \ No newline at end of file diff --git a/test/src/NexuslibTestRunner.as b/test/src/NexuslibTestRunner.as index 0eab4c7..f20e5dd 100644 --- a/test/src/NexuslibTestRunner.as +++ b/test/src/NexuslibTestRunner.as @@ -35,15 +35,6 @@ public class NexuslibTestRunner extends Sprite core.textPrinter.traceOnComplete = false; core.start(MainTestSuite, null, this); //core.start(PerformanceTestSuite, null, this); - - //this.setPrinter(new ResultPrinter(false, 0x333333, new TextFormat("Consolas", 12, 0xffffff))); - // NOTE: sending a particular class and method name will - // execute setUp(), the method and NOT tearDown. - // This allows you to get visual confirmation while developing - // visual entities - // start(AllTests, null, TestRunner.SHOW_TRACE); - - //start(MainTestSuite); } } diff --git a/test/src/test/nexus/math/AbstractIPRNGTest.as b/test/src/test/nexus/math/AbstractIPRNGTest.as new file mode 100644 index 0000000..5047cb3 --- /dev/null +++ b/test/src/test/nexus/math/AbstractIPRNGTest.as @@ -0,0 +1,206 @@ +// Copyright 2012 Malachi Griffie +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +package test.nexus.math +{ + +import asunit.framework.TestCase; + +import flash.utils.*; + +import nexus.math.*; + +/** + * ... + */ +public class AbstractIPRNGTest extends TestCase +{ + //-------------------------------------- + // CLASS CONSTANTS + //-------------------------------------- + + public static const DISTRIBUTION_ITERATIONS:int = 10000; + public static const STRESS_ITERATIONS:int = 1000000; + + //-------------------------------------- + // INSTANCE VARIABLES + //-------------------------------------- + + protected var m_generator:IPRNG; + + //-------------------------------------- + // CONSTRUCTOR + //-------------------------------------- + + public function AbstractIPRNGTest(testMethod:String = null) + { + super(testMethod); + } + + //-------------------------------------- + // SETUP & TEARDOWN + //-------------------------------------- + + override protected function setUp():void + { + + } + + override protected function tearDown():void + { + + } + + //-------------------------------------- + // TESTS + //-------------------------------------- + + public function test_monteCarlo():void + { + for(var x:int = 0; x < 10; ++x) + { + runMonteCarloTest(); + } + } + + public function off_test_performance():void + { + var start:int = getTimer(); + for(var x:int = 0; x < STRESS_ITERATIONS; ++x) + { + m_generator.next(); + } + var end:int = getTimer() - start; + trace("test_performance", m_generator, STRESS_ITERATIONS + " iterations: " + end + "ms"); + assertTrue(end < 800); + } + + public function test_randomInteger():void + { + var rand : Random = new Random(m_generator); + var highHit : Boolean = false; + var lowHit : Boolean = false; + const low : int = 1; + const high : int = 100; + for(var x : int = 0; x < DISTRIBUTION_ITERATIONS; ++x) + { + var num : int = rand.integer(low, high); + assertTrue(num + " is not <= " + high, num <= high); + assertTrue(num + " is not >= " + low, num >= low); + if(!lowHit && num == low) + { + lowHit = true; + } + if(!highHit && num == high) + { + highHit = true; + } + } + + assertTrue(high + " never generated", highHit); + assertTrue(low + " never generated", lowHit); + } + + public function test_randomFloat():void + { + var rand : Random = new Random(m_generator); + var highHit : Boolean = false; + var lowHit : Boolean = false; + const low : Number = 1.0; + const high : Number = 100.0; + for(var x : int = 0; x < DISTRIBUTION_ITERATIONS; ++x) + { + var num : int = rand.float(low, high); + assertTrue(num + " is not <= " + high, num <= high); + assertTrue(num + " is not >= " + low, num >= low); + if(!lowHit && num == low) + { + lowHit = true; + } + if(!highHit && num == high - 1) + { + highHit = true; + } + } + + assertTrue((high - 1).toFixed(1) + " never generated", highHit); + assertTrue(low.toFixed(1) + " never generated", lowHit); + } + + public function test_boolean():void + { + var rand : Random = new Random(m_generator); + var trueCount : int = 0; + var falseCount : int = 0; + for(var x : int = 0; x < DISTRIBUTION_ITERATIONS; ++x) + { + if(rand.boolean()) + { + trueCount++; + } + else + { + falseCount++; + } + } + var diff : int = Math.abs(trueCount - falseCount); + trace("test_boolean", m_generator, diff, trueCount, falseCount, diff / DISTRIBUTION_ITERATIONS * 100); + assertTrue((diff / DISTRIBUTION_ITERATIONS * 100) < 2.0); + } + + public function test_round1():void + { + var rand : Random = new Random(m_generator); + var upCount : int = 0; + var downCount : int = 0; + const num : Number = 4.5; + for(var x : int = 0; x < DISTRIBUTION_ITERATIONS; ++x) + { + if(rand.weightedRound(num) == 4) + { + downCount++; + } + else + { + upCount++; + } + } + var diff : int = Math.abs(upCount - downCount); + trace("test_round1", m_generator, diff, upCount, downCount, diff / DISTRIBUTION_ITERATIONS * 100); + assertTrue((diff / DISTRIBUTION_ITERATIONS * 100) < 2.0); + } + + //-------------------------------------- + // HELPER METHODS + //-------------------------------------- + + protected function runMonteCarloTest():void + { + var inCircle:int = 0; + for(var i:int = 0; i < DISTRIBUTION_ITERATIONS; ++i) + { + var xr:Number = m_generator.next() / m_generator.period; + var yr:Number = m_generator.next() / m_generator.period; + // find the calculated distance to the center + if((xr * xr) + (yr * yr) <= 1.0) + { + inCircle++; + } + } + + // calculate the Pi approximations + var calculatedPi:Number = inCircle / DISTRIBUTION_ITERATIONS * 4; + + // calculate the % error + var error:Number = Math.abs((calculatedPi - Math.PI) / Math.PI * 100); + + var resultText:String = "Random Pi Approximation: " + calculatedPi + " Error: " + (Math.floor(error * 100) / 100) + "%"; + //trace(m_generator + " " + resultText); + + assertTrue(resultText, error < 1.5); + } +} + +} \ No newline at end of file diff --git a/test/src/test/nexus/math/AbstractISeededPRNGTest.as b/test/src/test/nexus/math/AbstractISeededPRNGTest.as new file mode 100644 index 0000000..57f147b --- /dev/null +++ b/test/src/test/nexus/math/AbstractISeededPRNGTest.as @@ -0,0 +1,103 @@ +// Copyright 2012 Malachi Griffie +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +package test.nexus.math +{ + +import asunit.framework.TestCase; +import flash.utils.Dictionary; +import flash.utils.getTimer; + +import nexus.math.*; + +/** + * ... + */ +public class AbstractISeededPRNGTest extends AbstractIPRNGTest +{ + //-------------------------------------- + // CLASS CONSTANTS + //-------------------------------------- + + private static const DISTRIBUTION_ITERATIONS : int = 1000; + private static const STRESS_ITERATIONS : int = 1000000; + + //-------------------------------------- + // INSTANCE VARIABLES + //-------------------------------------- + + protected var m_algorithm : Class; + private var m_seededGenerator1 : ISeededPRNG; + private var m_seededGenerator2 : ISeededPRNG; + + //-------------------------------------- + // CONSTRUCTOR + //-------------------------------------- + + public function AbstractISeededPRNGTest(testMethod:String = null) + { + super(testMethod); + } + + //-------------------------------------- + // SETUP & TEARDOWN + //-------------------------------------- + + override protected function setUp():void + { + m_seededGenerator1 = new m_algorithm(); + m_seededGenerator1.seed = (new Date()).getTime(); + m_seededGenerator2 = new m_algorithm(); + m_seededGenerator2.seed = (new Date()).getTime() - getTimer(); + m_generator = m_seededGenerator1; + } + + override protected function tearDown():void + { + + } + + //-------------------------------------- + // TESTS + //-------------------------------------- + + public function test_seeds():void + { + assertEqualsArrays(get100(m_seededGenerator1, 0), get100(m_seededGenerator2, 0)); + assertEqualsArrays(get100(m_seededGenerator1, 1), get100(m_seededGenerator2, 1)); + assertEqualsArrays(get100(m_seededGenerator1, 2), get100(m_seededGenerator2, 2)); + assertEqualsArrays(get100(m_seededGenerator1, 1000), get100(m_seededGenerator2, 1000)); + //prime + assertEqualsArrays(get100(m_seededGenerator1, 214021), get100(m_seededGenerator2, 214021)); + + assertEqualsArrays(get100(m_seededGenerator1, int.MAX_VALUE), get100(m_seededGenerator2, int.MAX_VALUE)); + assertEqualsArrays(get100(m_seededGenerator1, int.MIN_VALUE), get100(m_seededGenerator2, int.MIN_VALUE)); + assertEqualsArrays(get100(m_seededGenerator1, uint.MAX_VALUE), get100(m_seededGenerator2, uint.MAX_VALUE)); + assertEqualsArrays(get100(m_seededGenerator1, uint.MIN_VALUE), get100(m_seededGenerator2, uint.MIN_VALUE)); + } + + //-------------------------------------- + // HELPER METHODS + //-------------------------------------- + + private function get100(prng : ISeededPRNG, seed:int):Array + { + prng.seed = seed; + var result : Array = []; + for(var x : int = 0; x < 100; ++x) + { + result[x] = prng.next(); + } + return result; + } + + override protected function runMonteCarloTest():void + { + m_seededGenerator1.seed = (new Date()).getTime(); + super.runMonteCarloTest(); + } +} + +} \ No newline at end of file diff --git a/test/src/test/nexus/math/LehmerGeneratorTest.as b/test/src/test/nexus/math/LehmerGeneratorTest.as new file mode 100644 index 0000000..c9b7491 --- /dev/null +++ b/test/src/test/nexus/math/LehmerGeneratorTest.as @@ -0,0 +1,56 @@ +// Copyright 2012 Malachi Griffie +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +package test.nexus.math +{ + +import asunit.framework.TestCase; +import nexus.math.LehmerGenerator; + +/** + * ... + */ +public class LehmerGeneratorTest extends AbstractISeededPRNGTest +{ + //-------------------------------------- + // CLASS CONSTANTS + //-------------------------------------- + + //-------------------------------------- + // INSTANCE VARIABLES + //-------------------------------------- + + //-------------------------------------- + // CONSTRUCTOR + //-------------------------------------- + + public function LehmerGeneratorTest(testMethod:String = null) + { + super(testMethod); + + } + + //-------------------------------------- + // SETUP & TEARDOWN + //-------------------------------------- + + override protected function setUp():void + { + m_algorithm = LehmerGenerator; + + super.setUp(); + } + + override protected function tearDown():void + { + super.tearDown(); + } + + //-------------------------------------- + // TESTS + //-------------------------------------- +} + +} \ No newline at end of file diff --git a/test/src/test/nexus/math/NativeRandomGeneratorTest.as b/test/src/test/nexus/math/NativeRandomGeneratorTest.as new file mode 100644 index 0000000..4c10711 --- /dev/null +++ b/test/src/test/nexus/math/NativeRandomGeneratorTest.as @@ -0,0 +1,40 @@ +// Copyright 2012 Malachi Griffie +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +package test.nexus.math +{ + +import asunit.framework.TestCase; +import nexus.math.NativeRandomGenerator; + +public class NativeRandomGeneratorTest extends AbstractIPRNGTest +{ + //-------------------------------------- + // CONSTRUCTOR + //-------------------------------------- + + public function NativeRandomGeneratorTest(testMethod:String = null) + { + super(testMethod); + } + + //-------------------------------------- + // SETUP & TEARDOWN + //-------------------------------------- + + override protected function setUp():void + { + m_generator = new NativeRandomGenerator(); + + super.setUp(); + } + + override protected function tearDown():void + { + super.tearDown(); + } +} + +} \ No newline at end of file