From d5be9a7c889e729cb468462ac2292507aae9274d Mon Sep 17 00:00:00 2001 From: Ali Moeeny Date: Fri, 19 Jul 2013 15:38:38 -0400 Subject: [PATCH 1/3] Create MTRandom64.h --- MTRandom/MTRandom64.h | 45 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 MTRandom/MTRandom64.h diff --git a/MTRandom/MTRandom64.h b/MTRandom/MTRandom64.h new file mode 100644 index 0000000..d00aff4 --- /dev/null +++ b/MTRandom/MTRandom64.h @@ -0,0 +1,45 @@ +// Attempt to port to 64bit by Ali Moeeny 7/19/2013 +// DO NOT USE IN PRODUCTION OR MISSION CRITICAL APPLICATION + +// MTRandom - Objective-C Mersenne Twister +// Objective-C interface by Adam Preble - adampreble.net - 8/6/12 + +#import + +@interface MTRandom64 : NSObject + +// Initialize with a given seed value. This is the designated initializer +- (id)initWithSeed:(uint64_t)seed; + +// Seed the generator with the current time. +- (id)init; + + +// generates a random number on [0,0xffffffffffffffff] interval +- (uint64_t)randomUInt64; + +// generates a random number on [0,1]-real-interval +- (double)randomDouble; + +// generates a random number on [0,1)-real-interval +- (double)randomDouble0To1Exclusive; + +@end + + +@interface MTRandom64 (Extras) + +- (BOOL)randomBool; + +- (uint64_t)randomUInt64From:(uint64_t)start to:(uint64_t)stop; + +- (double)randomDoubleFrom:(double)start to:(double)stop; + +@end + + +@interface NSArray (MTRandom64) + +- (id)mt_randomObjectWithRandom:(MTRandom64 *)r; + +@end From 4b5ac85d88c76d04dafea1491270c1f30cdf51ca Mon Sep 17 00:00:00 2001 From: Ali Moeeny Date: Fri, 19 Jul 2013 15:39:10 -0400 Subject: [PATCH 2/3] Create MTRandom64.m --- MTRandom/MTRandom64.m | 246 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 MTRandom/MTRandom64.m diff --git a/MTRandom/MTRandom64.m b/MTRandom/MTRandom64.m new file mode 100644 index 0000000..a45e6a8 --- /dev/null +++ b/MTRandom/MTRandom64.m @@ -0,0 +1,246 @@ +// Attempt to port to 64bit by Ali Moeeny 7/19/2013 +// DO NOT USE IN PRODUCTION OR MISSION CRITICAL APPLICATION + +// MTRandom - Objective-C Mersenne Twister +// Objective-C interface by Adam Preble - adampreble.net +// Based on mt19937ar.c; license is included directly below this comment block. +// http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c +// Portions adapted from code by MrFusion: http://forums.macrumors.com/showthread.php?t=1083103 + +/* + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) + */ + +/* Period parameters */ +#define N 624 +#define M 397 +#define MATRIX_A 0x9908b0dfUL /* constant vector a */ +#define UPPER_MASK 0x80000000UL /* most significant w-r bits */ +#define LOWER_MASK 0x7fffffffUL /* least significant r bits */ + +#import "MTRandom64.h" + +@interface MTRandom64 () { + uint64_t mt[N]; + uint64_t mti; +} + +@end + +@implementation MTRandom64 + +#pragma mark - +#pragma mark init + +- (id)init +{ + uint64_t seed = (uint64_t)[NSDate timeIntervalSinceReferenceDate]; + return [self initWithSeed:seed]; +} + +- (id)initWithSeed:(uint64_t)seed +{ + self = [super init]; + if (self != nil) + { + [self seed:seed]; + } + return self; +} + +#pragma mark - NSCoding + +- (id)initWithCoder:(NSCoder *)coder +{ + if ((self = [super init])) + { + mti = (uint64_t)[coder decodeIntegerForKey:@"mti"]; + + NSArray *arr = [coder decodeObjectForKey:@"mt"]; + if (!arr) + [NSException raise:@"MTRandom" format:@"No array in archive?"]; + + if (arr.count != N) + [NSException raise:@"MTRandom" format:@"Coded value has different N size."]; + + [arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + mt[idx] = (uint64_t)[obj unsignedIntegerValue]; + }]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)coder +{ + [coder encodeInteger:mti forKey:@"mti"]; + + NSMutableArray *arr = [NSMutableArray arrayWithCapacity:N]; + for (int i = 0; i < N; i++) + [arr addObject:@(mt[i])]; + [coder encodeObject:arr forKey:@"mt"]; +} + +#pragma mark - NSCopying + +- (id)copyWithZone:(NSZone *)zone +{ + MTRandom64 *r = [[[self class] allocWithZone:zone] init]; + r->mti = mti; + memcpy(r->mt, mt, sizeof(uint64_t) * N); + return r; +} + +#pragma mark - Mersenne Twister + +- (void)seed:(uint64_t)s +{ + mt[0]= s & 0xffffffffUL; + for (mti=1; mti> 30)) + mti); + /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ + /* In the previous versions, MSBs of the seed affect */ + /* only MSBs of the array mt[]. */ + /* 2002/01/09 modified by Makoto Matsumoto */ + mt[mti] &= 0xffffffffffffffffUL; + /* for >64 bit machines */ + } +} + +// generates a random number on [0,0xffffffff]-interval +- (uint64_t)randomUInt64 +{ + uint64_t y; + static uint64_t mag01[2]={0x0UL, MATRIX_A}; + /* mag01[x] = x * MATRIX_A for x=0,1 */ + + if (mti >= N) { /* generate N words at one time */ + int kk; + + if (mti == N+1) /* if init_genrand() has not been called, */ + [self seed:5489]; /* a default initial seed is used */ + + for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; + } + for (;kk> 1) ^ mag01[y & 0x1UL]; + } + y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); + mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; + + mti = 0; + } + + y = mt[mti++]; + + /* Tempering */ + y ^= (y >> 11); + y ^= (y << 7) & 0x9d2c5680UL; + y ^= (y << 15) & 0xefc60000UL; + y ^= (y >> 18); + + return y; +} + + +#pragma mark - Auxiliary Methods + +/* generates a random number on [0,1]-real-interval */ +- (double)randomDouble +{ + return [self randomUInt64]*(1.0/18446744073709551615.0); + /* divided by 2^64-1 */ +} + +/* generates a random number on [0,1)-real-interval */ +- (double)randomDouble0To1Exclusive +{ + return [self randomUInt64]*(1.0/18446744073709551616.0); + /* divided by 2^64 */ +} + +@end + + +#pragma mark - + + +@implementation MTRandom64 (Extras) + +- (BOOL)randomBool +{ + return ([self randomUInt64] / 2) < 2147483648; +// return [self randomUInt64] < 18446744073709551616;// <-64 | 32-> 2147483648; +} + +- (uint64_t)randomUInt64From:(uint64_t)start to:(uint64_t)stop +{ + NSUInteger width = 1 + stop - start; + + return start + (floor([self randomDouble0To1Exclusive] * (double)width)); +} + +- (double)randomDoubleFrom:(double)start to:(double)stop +{ + double range = stop - start; + double randomDouble = [self randomDouble]; + return start + randomDouble * range; +} + +@end + + +#pragma mark - + + +@implementation NSArray (MTRandom) + +- (id)mt_randomObjectWithRandom:(MTRandom64 *)r +{ + return [self objectAtIndex:[r randomUInt64From:0 to:(uint64_t)self.count-1]]; +} + +@end + From 5e503c597792817ec2240ecd7334cce2487c65e7 Mon Sep 17 00:00:00 2001 From: Ali Moeeny Date: Fri, 26 Jul 2013 20:12:00 -0400 Subject: [PATCH 3/3] MTRandom 64 is now working, and very basic tests are done, TESTS of RANDOMNESS are not done yet --- MTRandom.xcodeproj/project.pbxproj | 10 + .../xcshareddata/MTRandom.xccheckout | 39 +++ MTRandom/MTRandom.h | 21 +- MTRandom/MTRandom.m | 287 +++++++++-------- MTRandom/MTRandom64.h | 24 +- MTRandom/MTRandom64.m | 300 ++++++++++-------- MTRandomTests/mtrandom64Tests.m | 53 ++++ 7 files changed, 441 insertions(+), 293 deletions(-) create mode 100644 MTRandom.xcodeproj/project.xcworkspace/xcshareddata/MTRandom.xccheckout create mode 100644 MTRandomTests/mtrandom64Tests.m diff --git a/MTRandom.xcodeproj/project.pbxproj b/MTRandom.xcodeproj/project.pbxproj index 660c0dc..099c329 100644 --- a/MTRandom.xcodeproj/project.pbxproj +++ b/MTRandom.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 4138808117A3475400FB55B5 /* MTRandom64.m in Sources */ = {isa = PBXBuildFile; fileRef = 4138808017A3475400FB55B5 /* MTRandom64.m */; }; + 4138808317A3476100FB55B5 /* mtrandom64Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4138808217A3475D00FB55B5 /* mtrandom64Tests.m */; }; 6698DF8015F41C9B00B74390 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6698DF7F15F41C9B00B74390 /* SenTestingKit.framework */; }; 6698DF8715F41C9B00B74390 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6698DF8515F41C9B00B74390 /* InfoPlist.strings */; }; 6698DF8A15F41C9B00B74390 /* MTRandomTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6698DF8915F41C9B00B74390 /* MTRandomTests.m */; }; @@ -14,6 +16,9 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 4138807F17A3475400FB55B5 /* MTRandom64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MTRandom64.h; sourceTree = ""; }; + 4138808017A3475400FB55B5 /* MTRandom64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MTRandom64.m; sourceTree = ""; }; + 4138808217A3475D00FB55B5 /* mtrandom64Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = mtrandom64Tests.m; sourceTree = ""; }; 6698DF5B15F4103400B74390 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 6698DF7E15F41C9B00B74390 /* MTRandomTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MTRandomTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; 6698DF7F15F41C9B00B74390 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; @@ -70,6 +75,7 @@ 6698DF8215F41C9B00B74390 /* MTRandomTests */ = { isa = PBXGroup; children = ( + 4138808217A3475D00FB55B5 /* mtrandom64Tests.m */, 6698DF8815F41C9B00B74390 /* MTRandomTests.h */, 6698DF8915F41C9B00B74390 /* MTRandomTests.m */, 6698DF8315F41C9B00B74390 /* Supporting Files */, @@ -90,6 +96,8 @@ 6698DF9015F4449300B74390 /* MTRandom */ = { isa = PBXGroup; children = ( + 4138807F17A3475400FB55B5 /* MTRandom64.h */, + 4138808017A3475400FB55B5 /* MTRandom64.m */, 6698DF9615F4452100B74390 /* MTRandom.h */, 6698DF9715F4452100B74390 /* MTRandom.m */, ); @@ -175,8 +183,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4138808117A3475400FB55B5 /* MTRandom64.m in Sources */, 6698DF8A15F41C9B00B74390 /* MTRandomTests.m in Sources */, 6698DF9815F4452100B74390 /* MTRandom.m in Sources */, + 4138808317A3476100FB55B5 /* mtrandom64Tests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/MTRandom.xcodeproj/project.xcworkspace/xcshareddata/MTRandom.xccheckout b/MTRandom.xcodeproj/project.xcworkspace/xcshareddata/MTRandom.xccheckout new file mode 100644 index 0000000..7cf4749 --- /dev/null +++ b/MTRandom.xcodeproj/project.xcworkspace/xcshareddata/MTRandom.xccheckout @@ -0,0 +1,39 @@ + + + + + IDESourceControlProjectIdentifier + B44BD6B2-6E83-428F-A6A9-EBB0B9039421 + IDESourceControlProjectName + MTRandom + IDESourceControlProjectOriginsDictionary + + F8F761A8-19D3-4CA0-A183-7D2F7C83994C + ssh://github.com/alimoeeny/MTRandom.git + + IDESourceControlProjectPath + MTRandom.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + F8F761A8-19D3-4CA0-A183-7D2F7C83994C + ../.. + + IDESourceControlProjectURL + ssh://github.com/alimoeeny/MTRandom.git + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + F8F761A8-19D3-4CA0-A183-7D2F7C83994C + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + F8F761A8-19D3-4CA0-A183-7D2F7C83994C + IDESourceControlWCCName + MTRandom + + + + diff --git a/MTRandom/MTRandom.h b/MTRandom/MTRandom.h index 0dbfeb1..c931999 100644 --- a/MTRandom/MTRandom.h +++ b/MTRandom/MTRandom.h @@ -6,37 +6,34 @@ @interface MTRandom : NSObject // Initialize with a given seed value. This is the designated initializer -- (id)initWithSeed:(uint32_t)seed; +- (id) initWithSeed:(uint32_t)seed; // Seed the generator with the current time. -- (id)init; - +- (id) init; // generates a random number on [0,0xffffffff]-interval -- (uint32_t)randomUInt32; +- (uint32_t) randomUInt32; // generates a random number on [0,1]-real-interval -- (double)randomDouble; +- (double) randomDouble; // generates a random number on [0,1)-real-interval -- (double)randomDouble0To1Exclusive; +- (double) randomDouble0To1Exclusive; @end - @interface MTRandom (Extras) -- (BOOL)randomBool; +- (BOOL) randomBool; -- (uint32_t)randomUInt32From:(uint32_t)start to:(uint32_t)stop; +- (uint32_t) randomUInt32From:(uint32_t)start to:(uint32_t)stop; -- (double)randomDoubleFrom:(double)start to:(double)stop; +- (double) randomDoubleFrom:(double)start to:(double)stop; @end - @interface NSArray (MTRandom) -- (id)mt_randomObjectWithRandom:(MTRandom *)r; +- (id) mt_randomObjectWithRandom:(MTRandom *)r; @end diff --git a/MTRandom/MTRandom.m b/MTRandom/MTRandom.m index 8d085a7..72d39b4 100644 --- a/MTRandom/MTRandom.m +++ b/MTRandom/MTRandom.m @@ -5,46 +5,46 @@ // Portions adapted from code by MrFusion: http://forums.macrumors.com/showthread.php?t=1083103 /* - A C-program for MT19937, with initialization improved 2002/1/26. - Coded by Takuji Nishimura and Makoto Matsumoto. - - Before using, initialize the state by using init_genrand(seed) - or init_by_array(init_key, key_length). - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - Any feedback is very welcome. - http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html - email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) */ /* Period parameters */ @@ -57,8 +57,8 @@ or init_by_array(init_key, key_length). #import "MTRandom.h" @interface MTRandom () { - uint32_t mt[N]; - uint32_t mti; + uint32_t mt[N]; + uint32_t mti; } @end @@ -68,116 +68,144 @@ @implementation MTRandom #pragma mark - #pragma mark init -- (id)init +- (id) init { - uint32_t seed = (uint32_t)[NSDate timeIntervalSinceReferenceDate]; - return [self initWithSeed:seed]; + uint32_t seed = (uint32_t)[NSDate timeIntervalSinceReferenceDate]; + return [self initWithSeed:seed]; } -- (id)initWithSeed:(uint32_t)seed + +- (id) initWithSeed:(uint32_t)seed { - self = [super init]; - if (self != nil) - { - [self seed:seed]; - } - return self; + self = [super init]; + if (self != nil) + { + [self seed:seed]; + } + + return self; } + #pragma mark - NSCoding -- (id)initWithCoder:(NSCoder *)coder +- (id) initWithCoder:(NSCoder *)coder { - if ((self = [super init])) - { - mti = (uint32_t)[coder decodeIntegerForKey:@"mti"]; - - NSArray *arr = [coder decodeObjectForKey:@"mt"]; - if (!arr) - [NSException raise:@"MTRandom" format:@"No array in archive?"]; - - if (arr.count != N) - [NSException raise:@"MTRandom" format:@"Coded value has different N size."]; - - [arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - mt[idx] = (uint32_t)[obj unsignedIntegerValue]; - }]; - } - return self; + if ( (self = [super init]) ) + { + mti = (uint32_t)[coder decodeIntegerForKey : @"mti"]; + + NSArray *arr = [coder decodeObjectForKey:@"mt"]; + if (!arr) + { + [NSException raise:@"MTRandom" format:@"No array in archive?"]; + } + + if (arr.count != N) + { + [NSException raise:@"MTRandom" format:@"Coded value has different N size."]; + } + + [arr enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) { + mt[idx] = (uint32_t)[obj unsignedIntegerValue]; + } + + + ]; + } + + return self; } -- (void)encodeWithCoder:(NSCoder *)coder + +- (void) encodeWithCoder:(NSCoder *)coder { - [coder encodeInteger:mti forKey:@"mti"]; - - NSMutableArray *arr = [NSMutableArray arrayWithCapacity:N]; - for (int i = 0; i < N; i++) - [arr addObject:@(mt[i])]; - [coder encodeObject:arr forKey:@"mt"]; + [coder encodeInteger:mti forKey:@"mti"]; + + NSMutableArray *arr = [NSMutableArray arrayWithCapacity:N]; + for (int i = 0; i < N; i++) + { + [arr addObject:@(mt[i])]; + } + + [coder encodeObject:arr forKey:@"mt"]; } + #pragma mark - NSCopying -- (id)copyWithZone:(NSZone *)zone +- (id) copyWithZone:(NSZone *)zone { - MTRandom *r = [[[self class] allocWithZone:zone] init]; - r->mti = mti; - memcpy(r->mt, mt, sizeof(uint32_t) * N); - return r; + MTRandom *r = [[[self class] allocWithZone:zone] init]; + r->mti = mti; + memcpy(r->mt, mt, sizeof(uint32_t) * N); + return r; } + #pragma mark - Mersenne Twister -- (void)seed:(uint32_t)s +- (void) seed:(uint32_t)s { - mt[0]= s & 0xffffffffUL; - for (mti=1; mti> 30)) + mti); - /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ - /* In the previous versions, MSBs of the seed affect */ - /* only MSBs of the array mt[]. */ - /* 2002/01/09 modified by Makoto Matsumoto */ + (1812433253UL * ( mt[mti - 1] ^ (mt[mti - 1] >> 30) ) + mti); + /* + See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. + In the previous versions, MSBs of the seed affect + only MSBs of the array mt[]. + 2002/01/09 modified by Makoto Matsumoto + */ mt[mti] &= 0xffffffffUL; /* for >32 bit machines */ } } + // generates a random number on [0,0xffffffff]-interval -- (uint32_t)randomUInt32 +- (uint32_t) randomUInt32 { uint32_t y; - static uint32_t mag01[2]={0x0UL, MATRIX_A}; + static uint32_t mag01[2] = {0x0UL, MATRIX_A}; /* mag01[x] = x * MATRIX_A for x=0,1 */ - - if (mti >= N) { /* generate N words at one time */ + + if (mti >= N) /* generate N words at one time */ + { int kk; - - if (mti == N+1) /* if init_genrand() has not been called, */ + + if (mti == N + 1) /* if init_genrand() has not been called, */ + { [self seed:5489]; /* a default initial seed is used */ - - for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; } - for (;kk> 1) ^ mag01[y & 0x1UL]; + + for (kk = 0; kk < N - M; kk++) + { + y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK); + mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1UL]; + } + + for (; kk < N - 1; kk++) + { + y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK); + mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1UL]; } - y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); - mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; - + + y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK); + mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1UL]; + mti = 0; } - + y = mt[mti++]; - + /* Tempering */ y ^= (y >> 11); y ^= (y << 7) & 0x9d2c5680UL; y ^= (y << 15) & 0xefc60000UL; y ^= (y >> 18); - + return y; } @@ -185,58 +213,59 @@ - (uint32_t)randomUInt32 #pragma mark - Auxiliary Methods /* generates a random number on [0,1]-real-interval */ -- (double)randomDouble +- (double) randomDouble { - return [self randomUInt32]*(1.0/4294967295.0); + return [self randomUInt32] * (1.0 / 4294967295.0); /* divided by 2^32-1 */ } + /* generates a random number on [0,1)-real-interval */ -- (double)randomDouble0To1Exclusive +- (double) randomDouble0To1Exclusive { - return [self randomUInt32]*(1.0/4294967296.0); + return [self randomUInt32] * (1.0 / 4294967296.0); /* divided by 2^32 */ } -@end +@end #pragma mark - - @implementation MTRandom (Extras) -- (BOOL)randomBool +- (BOOL) randomBool { - return [self randomUInt32] < 2147483648; + return [self randomUInt32] < 2147483648; } -- (uint32_t)randomUInt32From:(uint32_t)start to:(uint32_t)stop + +- (uint32_t) randomUInt32From:(uint32_t)start to:(uint32_t)stop { - NSUInteger width = 1 + stop - start; - - return start + (floor([self randomDouble0To1Exclusive] * (double)width)); + NSUInteger width = 1 + stop - start; + + return start + ( floor([self randomDouble0To1Exclusive] * (double)width) ); } -- (double)randomDoubleFrom:(double)start to:(double)stop + +- (double) randomDoubleFrom:(double)start to:(double)stop { - double range = stop - start; - double randomDouble = [self randomDouble]; - return start + randomDouble * range; + double range = stop - start; + double randomDouble = [self randomDouble]; + return start + randomDouble * range; } -@end +@end #pragma mark - - @implementation NSArray (MTRandom) -- (id)mt_randomObjectWithRandom:(MTRandom *)r +- (id) mt_randomObjectWithRandom:(MTRandom *)r { - return [self objectAtIndex:[r randomUInt32From:0 to:(uint32_t)self.count-1]]; + return [self objectAtIndex:[r randomUInt32From:0 to:(uint32_t)self.count - 1]]; } -@end +@end diff --git a/MTRandom/MTRandom64.h b/MTRandom/MTRandom64.h index d00aff4..af82a87 100644 --- a/MTRandom/MTRandom64.h +++ b/MTRandom/MTRandom64.h @@ -1,6 +1,3 @@ -// Attempt to port to 64bit by Ali Moeeny 7/19/2013 -// DO NOT USE IN PRODUCTION OR MISSION CRITICAL APPLICATION - // MTRandom - Objective-C Mersenne Twister // Objective-C interface by Adam Preble - adampreble.net - 8/6/12 @@ -9,37 +6,34 @@ @interface MTRandom64 : NSObject // Initialize with a given seed value. This is the designated initializer -- (id)initWithSeed:(uint64_t)seed; +- (id) initWithSeed:(uint64_t)seed; // Seed the generator with the current time. -- (id)init; - +- (id) init; // generates a random number on [0,0xffffffffffffffff] interval -- (uint64_t)randomUInt64; +- (uint64_t) randomUInt64; // generates a random number on [0,1]-real-interval -- (double)randomDouble; +- (double) randomDouble; // generates a random number on [0,1)-real-interval -- (double)randomDouble0To1Exclusive; +- (double) randomDouble0To1Exclusive; @end - @interface MTRandom64 (Extras) -- (BOOL)randomBool; +- (BOOL) randomBool; -- (uint64_t)randomUInt64From:(uint64_t)start to:(uint64_t)stop; +- (uint64_t) randomUInt64From:(uint64_t)start to:(uint64_t)stop; -- (double)randomDoubleFrom:(double)start to:(double)stop; +- (double) randomDoubleFrom:(double)start to:(double)stop; @end - @interface NSArray (MTRandom64) -- (id)mt_randomObjectWithRandom:(MTRandom64 *)r; +- (id) mt_randomObjectWithRandom:(MTRandom64 *)r; @end diff --git a/MTRandom/MTRandom64.m b/MTRandom/MTRandom64.m index a45e6a8..28d433d 100644 --- a/MTRandom/MTRandom64.m +++ b/MTRandom/MTRandom64.m @@ -1,6 +1,3 @@ -// Attempt to port to 64bit by Ali Moeeny 7/19/2013 -// DO NOT USE IN PRODUCTION OR MISSION CRITICAL APPLICATION - // MTRandom - Objective-C Mersenne Twister // Objective-C interface by Adam Preble - adampreble.net // Based on mt19937ar.c; license is included directly below this comment block. @@ -8,60 +5,60 @@ // Portions adapted from code by MrFusion: http://forums.macrumors.com/showthread.php?t=1083103 /* - A C-program for MT19937, with initialization improved 2002/1/26. - Coded by Takuji Nishimura and Makoto Matsumoto. - - Before using, initialize the state by using init_genrand(seed) - or init_by_array(init_key, key_length). - - Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - 3. The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - Any feedback is very welcome. - http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html - email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) + A C-program for MT19937, with initialization improved 2002/1/26. + Coded by Takuji Nishimura and Makoto Matsumoto. + + Before using, initialize the state by using init_genrand(seed) + or init_by_array(init_key, key_length). + + Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The names of its contributors may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + Any feedback is very welcome. + http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html + email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) */ /* Period parameters */ -#define N 624 -#define M 397 -#define MATRIX_A 0x9908b0dfUL /* constant vector a */ -#define UPPER_MASK 0x80000000UL /* most significant w-r bits */ -#define LOWER_MASK 0x7fffffffUL /* least significant r bits */ +#define N 312 +#define M 156 +#define MATRIX_A 0xB5026F5AA96619E9ULL /* constant vector a */ +#define UPPER_MASK 0xFFFFFFFF80000000ULL /* most significant w-r bits */ +#define LOWER_MASK 0x7FFFFFFFULL /* least significant r bits */ #import "MTRandom64.h" @interface MTRandom64 () { - uint64_t mt[N]; - uint64_t mti; + uint64_t mt[N]; + uint64_t mti; } @end @@ -71,116 +68,144 @@ @implementation MTRandom64 #pragma mark - #pragma mark init -- (id)init +- (id) init { - uint64_t seed = (uint64_t)[NSDate timeIntervalSinceReferenceDate]; - return [self initWithSeed:seed]; + uint64_t seed = (uint64_t)[NSDate timeIntervalSinceReferenceDate]; + return [self initWithSeed:seed]; } -- (id)initWithSeed:(uint64_t)seed + +- (id) initWithSeed:(uint64_t)seed { - self = [super init]; - if (self != nil) - { - [self seed:seed]; - } - return self; + self = [super init]; + if (self != nil) + { + [self seed:seed]; + } + + return self; } + #pragma mark - NSCoding -- (id)initWithCoder:(NSCoder *)coder +- (id) initWithCoder:(NSCoder *)coder { - if ((self = [super init])) - { - mti = (uint64_t)[coder decodeIntegerForKey:@"mti"]; - - NSArray *arr = [coder decodeObjectForKey:@"mt"]; - if (!arr) - [NSException raise:@"MTRandom" format:@"No array in archive?"]; - - if (arr.count != N) - [NSException raise:@"MTRandom" format:@"Coded value has different N size."]; - - [arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - mt[idx] = (uint64_t)[obj unsignedIntegerValue]; - }]; - } - return self; + if ( (self = [super init]) ) + { + mti = (uint64_t)[coder decodeIntegerForKey : @"mti"]; + + NSArray *arr = [coder decodeObjectForKey:@"mt"]; + if (!arr) + { + [NSException raise:@"MTRandom" format:@"No array in archive?"]; + } + + if (arr.count != N) + { + [NSException raise:@"MTRandom" format:@"Coded value has different N size."]; + } + + [arr enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) { + mt[idx] = (uint64_t)[obj unsignedIntegerValue]; + } + + + ]; + } + + return self; } -- (void)encodeWithCoder:(NSCoder *)coder + +- (void) encodeWithCoder:(NSCoder *)coder { - [coder encodeInteger:mti forKey:@"mti"]; - - NSMutableArray *arr = [NSMutableArray arrayWithCapacity:N]; - for (int i = 0; i < N; i++) - [arr addObject:@(mt[i])]; - [coder encodeObject:arr forKey:@"mt"]; + [coder encodeInteger:mti forKey:@"mti"]; + + NSMutableArray *arr = [NSMutableArray arrayWithCapacity:N]; + for (int i = 0; i < N; i++) + { + [arr addObject:@(mt[i])]; + } + + [coder encodeObject:arr forKey:@"mt"]; } + #pragma mark - NSCopying -- (id)copyWithZone:(NSZone *)zone +- (id) copyWithZone:(NSZone *)zone { - MTRandom64 *r = [[[self class] allocWithZone:zone] init]; - r->mti = mti; - memcpy(r->mt, mt, sizeof(uint64_t) * N); - return r; + MTRandom64 *r = [[[self class] allocWithZone:zone] init]; + r->mti = mti; + memcpy(r->mt, mt, sizeof(uint64_t) * N); + return r; } + #pragma mark - Mersenne Twister -- (void)seed:(uint64_t)s +- (void) seed:(uint64_t)s { - mt[0]= s & 0xffffffffUL; - for (mti=1; mti> 30)) + mti); - /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ - /* In the previous versions, MSBs of the seed affect */ - /* only MSBs of the array mt[]. */ - /* 2002/01/09 modified by Makoto Matsumoto */ + (1812433253UL * ( mt[mti - 1] ^ (mt[mti - 1] >> 30) ) + mti); + /* + See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. + In the previous versions, MSBs of the seed affect + only MSBs of the array mt[]. + 2002/01/09 modified by Makoto Matsumoto + */ mt[mti] &= 0xffffffffffffffffUL; /* for >64 bit machines */ } } + // generates a random number on [0,0xffffffff]-interval -- (uint64_t)randomUInt64 +- (uint64_t) randomUInt64 { uint64_t y; - static uint64_t mag01[2]={0x0UL, MATRIX_A}; + static uint64_t mag01[2] = {0x0UL, MATRIX_A}; /* mag01[x] = x * MATRIX_A for x=0,1 */ - - if (mti >= N) { /* generate N words at one time */ + + if (mti >= N) /* generate N words at one time */ + { int kk; - - if (mti == N+1) /* if init_genrand() has not been called, */ + + if (mti == N + 1) /* if init_genrand() has not been called, */ + { [self seed:5489]; /* a default initial seed is used */ - - for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; } - for (;kk> 1) ^ mag01[y & 0x1UL]; + + for (kk = 0; kk < N - M; kk++) + { + y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK); + mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1UL]; + } + + for (; kk < N - 1; kk++) + { + y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK); + mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1UL]; } - y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); - mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; - + + y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK); + mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1UL]; + mti = 0; } - + y = mt[mti++]; - + /* Tempering */ y ^= (y >> 11); y ^= (y << 7) & 0x9d2c5680UL; y ^= (y << 15) & 0xefc60000UL; y ^= (y >> 18); - + return y; } @@ -188,59 +213,60 @@ - (uint64_t)randomUInt64 #pragma mark - Auxiliary Methods /* generates a random number on [0,1]-real-interval */ -- (double)randomDouble +- (double) randomDouble { - return [self randomUInt64]*(1.0/18446744073709551615.0); + return [self randomUInt64] * (1.0 / 18446744073709551615.0); /* divided by 2^64-1 */ } + /* generates a random number on [0,1)-real-interval */ -- (double)randomDouble0To1Exclusive +- (double) randomDouble0To1Exclusive { - return [self randomUInt64]*(1.0/18446744073709551616.0); + return [self randomUInt64] * (1.0 / 18446744073709551616.0); /* divided by 2^64 */ } -@end +@end #pragma mark - - @implementation MTRandom64 (Extras) -- (BOOL)randomBool +- (BOOL) randomBool { - return ([self randomUInt64] / 2) < 2147483648; + return ([self randomUInt64] / 2) < 2147483648; // return [self randomUInt64] < 18446744073709551616;// <-64 | 32-> 2147483648; } -- (uint64_t)randomUInt64From:(uint64_t)start to:(uint64_t)stop + +- (uint64_t) randomUInt64From:(uint64_t)start to:(uint64_t)stop { - NSUInteger width = 1 + stop - start; - - return start + (floor([self randomDouble0To1Exclusive] * (double)width)); + NSUInteger width = 1 + stop - start; + + return start + ( floor([self randomDouble0To1Exclusive] * (double)width) ); } -- (double)randomDoubleFrom:(double)start to:(double)stop + +- (double) randomDoubleFrom:(double)start to:(double)stop { - double range = stop - start; - double randomDouble = [self randomDouble]; - return start + randomDouble * range; + double range = stop - start; + double randomDouble = [self randomDouble]; + return start + randomDouble * range; } -@end +@end #pragma mark - - @implementation NSArray (MTRandom) -- (id)mt_randomObjectWithRandom:(MTRandom64 *)r +- (id) mt_randomObjectWithRandom:(MTRandom64 *)r { - return [self objectAtIndex:[r randomUInt64From:0 to:(uint64_t)self.count-1]]; + return [self objectAtIndex:[r randomUInt64From:0 to:(uint64_t)self.count - 1]]; } -@end +@end diff --git a/MTRandomTests/mtrandom64Tests.m b/MTRandomTests/mtrandom64Tests.m new file mode 100644 index 0000000..8cb6e8e --- /dev/null +++ b/MTRandomTests/mtrandom64Tests.m @@ -0,0 +1,53 @@ +// +// mtrandom64Tests.m +// mtrandom64Tests +// +// Created by Ali Moeeny on 7/19/13. +// Copyright (c) 2013 Ali Moeeny. All rights reserved. +// + +#import +#import "MTRandom64.h" + +@interface mtrandom64Tests : XCTestCase + +@property (strong) MTRandom64 * engine64; + +@end + +@implementation mtrandom64Tests + +- (void)setUp +{ + [super setUp]; +} + +- (void)tearDown +{ + [super tearDown]; +} + +- (void) testTheBasics_randomUInt64 +{ + _engine64 = [[MTRandom64 alloc] init]; + uint64_t r = 0; + for (int i=0; i < 1000; i++) { + r = [_engine64 randomUInt64]; + XCTAssertTrue(r>0); + XCTAssertTrue(r0); + XCTAssertTrue(r<1); + } +} + + +@end