Rebase the isaac random algorithm implementation.

This commit is contained in:
atomicint
2015-04-10 15:37:02 -04:00
parent b323a7625b
commit 7a2d933a5f
+145 -163
View File
@@ -31,58 +31,49 @@ public final class IsaacRandom {
private static final int GOLDEN_RATIO = 0x9e3779b9; private static final int GOLDEN_RATIO = 0x9e3779b9;
/** /**
* The log of the size of the result and memory arrays. * The log of the size of the result and state arrays.
*/ */
private static final int LOG_SIZE = 8; private static final int LOG_SIZE = Long.BYTES;
/** /**
* The size of the result and memory arrays. * The size of the result and states arrays.
*/ */
private static final int SIZE = 1 << LOG_SIZE; private static final int SIZE = 1 << LOG_SIZE;
/** /**
* A mask for pseudorandom lookup. * A mask for pseudo-random lookup.
*/ */
private static int MASK = SIZE - 1 << 2; private static int MASK = SIZE - 1 << 2;
/** /**
* The accumulator. * The results given to the user.
*/ */
private int a; private final int[] results = new int[SIZE];
/**
* The last result.
*/
private int b;
/**
* The counter.
*/
private int c;
/**
* The count through the results in the results array.
*/
private int count;
/** /**
* The internal state. * The internal state.
*/ */
private final int[] mem; private final int[] state = new int[SIZE];
/** /**
* The results given to the user. * The count through the results in the results array.
*/ */
private final int[] rsl; private int count = SIZE;
/** /**
* Creates the random number generator without an initial seed. * The accumulator.
*/ */
public IsaacRandom() { private int accumulator;
mem = new int[SIZE];
rsl = new int[SIZE]; /**
init(false); * The last result.
} */
private int last;
/**
* The counter.
*/
private int counter;
/** /**
* Creates the random number generator with the specified seed. * Creates the random number generator with the specified seed.
@@ -90,20 +81,75 @@ public final class IsaacRandom {
* @param seed The seed. * @param seed The seed.
*/ */
public IsaacRandom(int[] seed) { public IsaacRandom(int[] seed) {
mem = new int[SIZE]; int length = Math.min(seed.length, results.length);
rsl = new int[SIZE]; System.arraycopy(seed, 0, results, 0, length);
for (int i = 0; i < seed.length; ++i) { init();
rsl[i] = seed[i];
}
init(true);
} }
/** /**
* Initialises this random number generator. * Generates 256 results.
*
* @param hasSeed Set to {@code true} if a seed was passed to the constructor.
*/ */
private void init(boolean hasSeed) { private void isaac() {
int i, j, x, y;
last += ++counter;
for (i = 0, j = SIZE / 2; i < SIZE / 2;) {
x = state[i];
accumulator ^= accumulator << 13;
accumulator += state[j++];
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
x = state[i];
accumulator ^= accumulator >>> 6;
accumulator += state[j++];
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
x = state[i];
accumulator ^= accumulator << 2;
accumulator += state[j++];
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
x = state[i];
accumulator ^= accumulator >>> 16;
accumulator += state[j++];
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
}
for (j = 0; j < SIZE / 2;) {
x = state[i];
accumulator ^= accumulator << 13;
accumulator += state[j++];
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
x = state[i];
accumulator ^= accumulator >>> 6;
accumulator += state[j++];
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
x = state[i];
accumulator ^= accumulator << 2;
accumulator += state[j++];
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
x = state[i];
accumulator ^= accumulator >>> 16;
accumulator += state[j++];
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
}
}
/**
* Initializes this random number generator.
*/
private void init() {
int i; int i;
int a, b, c, d, e, f, g, h; int a, b, c, d, e, f, g, h;
a = b = c = d = e = f = g = h = GOLDEN_RATIO; a = b = c = d = e = f = g = h = GOLDEN_RATIO;
@@ -136,16 +182,15 @@ public final class IsaacRandom {
} }
for (i = 0; i < SIZE; i += 8) { /* fill in mem[] with messy stuff */ for (i = 0; i < SIZE; i += 8) { /* fill in mem[] with messy stuff */
if (hasSeed) { a += results[i];
a += rsl[i]; b += results[i + 1];
b += rsl[i + 1]; c += results[i + 2];
c += rsl[i + 2]; d += results[i + 3];
d += rsl[i + 3]; e += results[i + 4];
e += rsl[i + 4]; f += results[i + 5];
f += rsl[i + 5]; g += results[i + 6];
g += rsl[i + 6]; h += results[i + 7];
h += rsl[i + 7];
}
a ^= b << 11; a ^= b << 11;
d += a; d += a;
b += c; b += c;
@@ -170,123 +215,60 @@ public final class IsaacRandom {
h ^= a >>> 9; h ^= a >>> 9;
c += h; c += h;
a += b; a += b;
mem[i] = a; state[i] = a;
mem[i + 1] = b; state[i + 1] = b;
mem[i + 2] = c; state[i + 2] = c;
mem[i + 3] = d; state[i + 3] = d;
mem[i + 4] = e; state[i + 4] = e;
mem[i + 5] = f; state[i + 5] = f;
mem[i + 6] = g; state[i + 6] = g;
mem[i + 7] = h; state[i + 7] = h;
} }
if (hasSeed) { /* second pass makes all of seed affect all of mem */ for (i = 0; i < SIZE; i += 8) {
for (i = 0; i < SIZE; i += 8) { a += state[i];
a += mem[i]; b += state[i + 1];
b += mem[i + 1]; c += state[i + 2];
c += mem[i + 2]; d += state[i + 3];
d += mem[i + 3]; e += state[i + 4];
e += mem[i + 4]; f += state[i + 5];
f += mem[i + 5]; g += state[i + 6];
g += mem[i + 6]; h += state[i + 7];
h += mem[i + 7]; a ^= b << 11;
a ^= b << 11; d += a;
d += a; b += c;
b += c; b ^= c >>> 2;
b ^= c >>> 2; e += b;
e += b; c += d;
c += d; c ^= d << 8;
c ^= d << 8; f += c;
f += c; d += e;
d += e; d ^= e >>> 16;
d ^= e >>> 16; g += d;
g += d; e += f;
e += f; e ^= f << 10;
e ^= f << 10; h += e;
h += e; f += g;
f += g; f ^= g >>> 4;
f ^= g >>> 4; a += f;
a += f; g += h;
g += h; g ^= h << 8;
g ^= h << 8; b += g;
b += g; h += a;
h += a; h ^= a >>> 9;
h ^= a >>> 9; c += h;
c += h; a += b;
a += b; state[i] = a;
mem[i] = a; state[i + 1] = b;
mem[i + 1] = b; state[i + 2] = c;
mem[i + 2] = c; state[i + 3] = d;
mem[i + 3] = d; state[i + 4] = e;
mem[i + 4] = e; state[i + 5] = f;
mem[i + 5] = f; state[i + 6] = g;
mem[i + 6] = g; state[i + 7] = h;
mem[i + 7] = h;
}
} }
isaac(); isaac();
count = SIZE;
}
/**
* Generates 256 results.
*/
private void isaac() {
int i, j, x, y;
b += ++c;
for (i = 0, j = SIZE / 2; i < SIZE / 2;) {
x = mem[i];
a ^= a << 13;
a += mem[j++];
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
rsl[i++] = b = mem[(y >> LOG_SIZE & MASK) >> 2] + x;
x = mem[i];
a ^= a >>> 6;
a += mem[j++];
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
rsl[i++] = b = mem[(y >> LOG_SIZE & MASK) >> 2] + x;
x = mem[i];
a ^= a << 2;
a += mem[j++];
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
rsl[i++] = b = mem[(y >> LOG_SIZE & MASK) >> 2] + x;
x = mem[i];
a ^= a >>> 16;
a += mem[j++];
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
rsl[i++] = b = mem[(y >> LOG_SIZE & MASK) >> 2] + x;
}
for (j = 0; j < SIZE / 2;) {
x = mem[i];
a ^= a << 13;
a += mem[j++];
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
rsl[i++] = b = mem[(y >> LOG_SIZE & MASK) >> 2] + x;
x = mem[i];
a ^= a >>> 6;
a += mem[j++];
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
rsl[i++] = b = mem[(y >> LOG_SIZE & MASK) >> 2] + x;
x = mem[i];
a ^= a << 2;
a += mem[j++];
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
rsl[i++] = b = mem[(y >> LOG_SIZE & MASK) >> 2] + x;
x = mem[i];
a ^= a >>> 16;
a += mem[j++];
mem[i] = y = mem[(x & MASK) >> 2] + a + b;
rsl[i++] = b = mem[(y >> LOG_SIZE & MASK) >> 2] + x;
}
} }
/** /**
@@ -299,7 +281,7 @@ public final class IsaacRandom {
isaac(); isaac();
count = SIZE - 1; count = SIZE - 1;
} }
return rsl[count]; return results[count];
} }
} }