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

        

Reply via email to