[
https://issues.apache.org/jira/browse/MATH-710?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Eldar Agalarov updated MATH-710:
--------------------------------
Description:
Dear developers, please add to Common Math library support for ISAAC random
number generator. This is a free and open-source PRNG
(http://burtleburtle.net/bob/rand/isaacafa.html).
Algorithm's rewrited (with some improvements) Java code from original C version:
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());
}
}
}
was:
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());
}
}
}
> 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
> Original Estimate: 1h
> Remaining Estimate: 1h
>
> Dear developers, please add to Common Math library support for ISAAC random
> number generator. This is a free and open-source PRNG
> (http://burtleburtle.net/bob/rand/isaacafa.html).
> Algorithm's rewrited (with some improvements) Java code from original C
> version:
> 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