Add support for fast cryptographically secure pseudorandom number generator ISAAC ---------------------------------------------------------------------------------
Key: MATH-710 URL: https://issues.apache.org/jira/browse/MATH-710 Project: Commons Math Issue Type: New Feature Affects Versions: 2.2 Reporter: Eldar Agalarov Dear developers, please add to Common Math library support for ISAAC random number generator. This is a free and open-source PRNG. Java code is below: import java.io.Serializable; public final class ISAACRandom extends AbstractRandom implements Serializable, Cloneable { private static final long serialVersionUID = 7288197941165002400L; private static final int SIZE_L = 8; /* log of size of rsl[] and mem[] */ private static final int SIZE = 1 << SIZE_L; /* size of rsl[] and mem[] */ private static final int H_SIZE = SIZE >> 1; /* half-size of rsl[] and mem[] */ private static final int MASK = SIZE - 1 << 2; /* for pseudorandom lookup */ private static final int GLD_RATIO = 0x9e3779b9; /* the golden ratio */ private static final long SEED_MASK = 0xffffffffL; private int[] rsl; /* the results given to the user */ private int[] mem; /* the internal state */ private int[] arr; private int count; /* count through the results in rsl[] */ private int a; /* accumulator */ private int b; /* the last result */ private int c; /* counter, guarantees cycle is at least 2^^40 */ private transient int x; private transient int i; private transient int j; public ISAACRandom() { this(System.currentTimeMillis()); } public ISAACRandom(long seed) { allocArrays(); setSeed(seed); } public ISAACRandom(int[] seed) { allocArrays(); setSeed(seed); } private void allocArrays() { rsl = new int[SIZE]; mem = new int[SIZE]; arr = new int[8]; } @Override public void setSeed(int seed) { setSeed(new int[]{seed}); } @Override public void setSeed(long seed) { setSeed(new int[]{(int) (seed >>> 32), (int) (seed & SEED_MASK)}); } @Override public void setSeed(int[] seed) { int seedLen = seed.length, rslLen = rsl.length; System.arraycopy(seed, 0, rsl, 0, Math.min(seedLen, rslLen)); if (seedLen < rslLen) { for (i = seedLen; i < rslLen; i++) { long k = rsl[i - seedLen]; rsl[i] = (int) (0x6c078965L * (k ^ k >> 30) + i & SEED_MASK); } } initState(); isaac(); count = SIZE - 1; } @Override protected int next(int bits) { if (count < 0) { isaac(); count = SIZE - 1; } return rsl[count--] >>> 32 - bits; } private void isaac() { i = 0; j = H_SIZE; b += ++c; while (i < H_SIZE) isaac2(); j = 0; while (j < H_SIZE) isaac2(); } private void isaac2() { x = mem[i]; a ^= a << 13; a += mem[j++]; isaac3(); x = mem[i]; a ^= a >>> 6; a += mem[j++]; isaac3(); x = mem[i]; a ^= a << 2; a += mem[j++]; isaac3(); x = mem[i]; a ^= a >>> 16; a += mem[j++]; isaac3(); } private void isaac3() { mem[i] = mem[(x & MASK) >> 2] + a + b; b = mem[(mem[i] >> SIZE_L & MASK) >> 2] + x; rsl[i++] = b; } private void initState() { a = b = c = 0; arr[0] = arr[1] = arr[2] = arr[3] = arr[4] = arr[5] = arr[6] = arr[7] = GLD_RATIO; for (i = 0; i < 4; i++) shuffle(); for (i = 0; i < SIZE; i++) mem[i] = rsl[i] = 0; for (i = 0; i < SIZE; i += 8) { arr[0] += rsl[i]; arr[1] += rsl[i + 1]; arr[2] += rsl[i + 2]; arr[3] += rsl[i + 3]; arr[4] += rsl[i + 4]; arr[5] += rsl[i + 5]; arr[6] += rsl[i + 6]; arr[7] += rsl[i + 7]; shuffle(); setState(); } for (i = 0; i < SIZE; i += 8) { arr[0] += mem[i]; arr[1] += mem[i + 1]; arr[2] += mem[i + 2]; arr[3] += mem[i + 3]; arr[4] += mem[i + 4]; arr[5] += mem[i + 5]; arr[6] += mem[i + 6]; arr[7] += mem[i + 7]; shuffle(); setState(); } } private void shuffle() { arr[0] ^= arr[1] << 11; arr[3] += arr[0]; arr[1] += arr[2]; arr[1] ^= arr[2] >>> 2; arr[4] += arr[1]; arr[2] += arr[3]; arr[2] ^= arr[3] << 8; arr[5] += arr[2]; arr[3] += arr[4]; arr[3] ^= arr[4] >>> 16; arr[6] += arr[3]; arr[4] += arr[5]; arr[4] ^= arr[5] << 10; arr[7] += arr[4]; arr[5] += arr[6]; arr[5] ^= arr[6] >>> 4; arr[0] += arr[5]; arr[6] += arr[7]; arr[6] ^= arr[7] << 8; arr[1] += arr[6]; arr[7] += arr[0]; arr[7] ^= arr[0] >>> 9; arr[2] += arr[7]; arr[0] += arr[1]; } private void setState() { mem[i] = arr[0]; mem[i + 1] = arr[1]; mem[i + 2] = arr[2]; mem[i + 3] = arr[3]; mem[i + 4] = arr[4]; mem[i + 5] = arr[5]; mem[i + 6] = arr[6]; mem[i + 7] = arr[7]; } @Override public ISAACRandom clone() { try { ISAACRandom cloned = (ISAACRandom) super.clone(); cloned.rsl = rsl.clone(); cloned.mem = mem.clone(); cloned.arr = arr.clone(); return cloned; } catch (CloneNotSupportedException e) { throw new InternalError(e.getMessage()); } } } -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa For more information on JIRA, see: http://www.atlassian.com/software/jira