Last active
September 21, 2016 15:54
-
-
Save cogmission/c4cb8feaba19595dae8ff964e18b05d0 to your computer and use it in GitHub Desktop.
UniversalRandom Using George Marsaglia's elegant Xorshift (In Python and Java)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ''' | |
| Created on Jul 31, 2016 | |
| @author: cogmission | |
| ''' | |
| class UniversalRandom(object): | |
| ''' | |
| classdocs | |
| ''' | |
| def __init__(self, seed): | |
| ''' | |
| Constructor | |
| ''' | |
| self.seed = seed | |
| def rshift(self, val, n): | |
| return val>>n if val >= 0 else (val+0x100000000)>>n | |
| def nextInt(self, bound): | |
| ''' doc ''' | |
| if bound <= 0: | |
| raise ValueError('bound must be positive') | |
| r = self.next(31) | |
| m = bound - 1 | |
| if (bound & m) == 0: | |
| r = (bound * r) >> 31 | |
| else: | |
| u = r | |
| r = u % bound | |
| while u - r + m < 0: | |
| u = self.next(31) | |
| return r | |
| def next(self, nbits): | |
| ''' doc ''' | |
| x = self.seed & 0xffffffffffffffff | |
| x ^= (x << 21) & 0xffffffffffffffff | |
| x ^= self.rshift(x, 35) & 0xffffffffffffffff | |
| x ^= (x << 4) & 0xffffffffffffffff | |
| self.seed = x | |
| x &= ((1 << nbits) - 1) & 0xffffffffffffffff | |
| return x | |
| if __name__ == '__main__': | |
| random = UniversalRandom(42) | |
| s = 2858730232218250 | |
| e = random.rshift(s, 35) | |
| print "e = " + str(e) | |
| x = random.nextInt(50) | |
| print "x = " + str(x) | |
| x = random.nextInt(50) | |
| print "x = " + str(x) | |
| x = random.nextInt(50) | |
| print "x = " + str(x) | |
| x = random.nextInt(50) | |
| print "x = " + str(x) | |
| x = random.nextInt(50) | |
| print "x = " + str(x) | |
| for i in xrange(0, 10): | |
| o = random.nextInt(50) | |
| print "x = " + str(o) | |
| ###################################### | |
| ## Values Seen in Java ## | |
| ###################################### | |
| ''' | |
| e = 83200 | |
| x = 0 | |
| x = 26 | |
| x = 14 | |
| x = 15 | |
| x = 38 | |
| x = 47 | |
| x = 13 | |
| x = 9 | |
| x = 15 | |
| x = 31 | |
| x = 6 | |
| x = 3 | |
| x = 0 | |
| x = 21 | |
| x = 45 | |
| ''' | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package org.numenta.nupic.util; | |
| public class UniversalRandom { | |
| long seed; | |
| static final String BadBound = "bound must be positive"; | |
| public UniversalRandom(long seed) { | |
| this.seed = seed; | |
| } | |
| public int nextInt() { | |
| return next(32); | |
| } | |
| public int nextInt(int bound) { | |
| if (bound <= 0) | |
| throw new IllegalArgumentException(BadBound); | |
| int r = next(31); | |
| int m = bound - 1; | |
| if ((bound & m) == 0) // i.e., bound is a power of 2 | |
| r = (int)((bound * (long)r) >> 31); | |
| else { | |
| for (int u = r; | |
| u - (r = u % bound) + m < 0; | |
| u = next(31)) | |
| ; | |
| } | |
| return r; | |
| } | |
| /** | |
| * Implementation of George Marsaglia's elegant Xorshift random generator | |
| * 30% faster and better quality than the built-in java.util.random see also | |
| * see http://www.javamex.com/tutorials/random_numbers/xorshift.shtml | |
| */ | |
| protected int next(int nbits) { | |
| long x = seed; | |
| x ^= (x << 21); | |
| x ^= (x >>> 35); | |
| x ^= (x << 4); | |
| seed = x; | |
| x &= ((1L << nbits) - 1); | |
| return (int) x; | |
| } | |
| public static void main(String[] args) { | |
| UniversalRandom random = new UniversalRandom(42); | |
| long s = 2858730232218250L; | |
| long e = (s >>> 35); | |
| System.out.println("e = " + e); | |
| int x = random.nextInt(50); | |
| System.out.println("x = " + x); | |
| x = random.nextInt(50); | |
| System.out.println("x = " + x); | |
| x = random.nextInt(50); | |
| System.out.println("x = " + x); | |
| x = random.nextInt(50); | |
| System.out.println("x = " + x); | |
| x = random.nextInt(50); | |
| System.out.println("x = " + x); | |
| for(int i = 0;i < 10;i++) { | |
| int o = random.nextInt(50); | |
| System.out.println("x = " + o); | |
| } | |
| /////////////////////////////////// | |
| // Values Seen in Python // | |
| /////////////////////////////////// | |
| /* | |
| * e = 83200 | |
| x = 0 | |
| x = 26 | |
| x = 14 | |
| x = 15 | |
| x = 38 | |
| x = 47 | |
| x = 13 | |
| x = 9 | |
| x = 15 | |
| x = 31 | |
| x = 6 | |
| x = 3 | |
| x = 0 | |
| x = 21 | |
| x = 45 | |
| */ | |
| } | |
| } |
Author
Author
Added universal nextDouble() method to both
Author
- Added universal
sample()method to both - Changed Java version of compatibility with the "fast" mode of Python via
nextX() - Added Optional mode
compatibility_modeargument to the Python UniversalRandom constructor which will then afford the option of using the fastest mode (compatibility_mode == False), or the compatible mode (compatibility_mode == True) which calls a different method which emulates Java overflows so that their outputs are identical.
Author
Added tweak to plain java: nextInt(), python: nextIntNB() calls to internally call the bounded method with Java's maximum integer value.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Added ability to set the seed value after construction.