Skip to content

Instantly share code, notes, and snippets.

@cogmission
Last active September 21, 2016 15:54
Show Gist options
  • Select an option

  • Save cogmission/c4cb8feaba19595dae8ff964e18b05d0 to your computer and use it in GitHub Desktop.

Select an option

Save cogmission/c4cb8feaba19595dae8ff964e18b05d0 to your computer and use it in GitHub Desktop.
UniversalRandom Using George Marsaglia's elegant Xorshift (In Python and Java)
'''
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
'''
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
*/
}
}
@cogmission
Copy link
Author

Added ability to set the seed value after construction.

@cogmission
Copy link
Author

Added universal nextDouble() method to both

@cogmission
Copy link
Author

  • Added universal sample() method to both
  • Changed Java version of compatibility with the "fast" mode of Python via nextX()
  • Added Optional mode compatibility_mode argument 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.

@cogmission
Copy link
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