This Common Lisp version is roughly as fast as Jenkins' optimised rand.c when compiled with SBCL.

UPDATE 04/10/2014

Version number incremented to 1.0.4; added INIT-SELF-SEED for stronger cryptographic randomization.

-- "the Phoeron" Colin J.E. Lupton

UPDATE 03/20/2014

CL-ISAAC v1.0.3, including ISAAC-64 algorithm, now available in the March 2014 Quicklisp update.

If you find any bugs, please report them at: https://github.com/thephoeron/cl-isaac/issues

-- "the Phoeron" Colin J.E. Lupton

USAGE

Make sure you have the latest Quicklisp distribution. Include CL-ISAAC as a dependency in your system definition, or evaluate (ql:quickload "cl-isaac") from the REPL.

First, you need to create an isaac context. If you have a 64-bit implementation of Lisp on an x86-64 platform, you can set :is64 t to take advantage of the ISAAC-64 algorithm. There are four functions that do this:

isaac:init-self-seed &key (count 1) (is64 nil) => <isaac context>

RECOMMENDED: First round seeds with random bits generated by init-kernel-seed, each additional round below count scrambles and modular adds the context values to more random bits from a new isaac context. A count > 3 is recommended for optimal speed vs. cryptographic strength.

isaac:init-kernel-seed &key (is64 nil) => <isaac context>

Seeds with values from /dev/arandom on BSD or /dev/urandom on Linux. Reads 1024 bytes from the device.

Seeds with all 0s. Always results in the same stream. For comparing with Jenkins' reference implementations.

These are functions you can pass an isaac context to. They will modify the isaac context and return a random value:

isaac:rand32<isaac context> => <random 32-bit value>

Uses the ISAAC-32 algorithm to generate a new random value.

isaac:rand-bits<isaac context><N> => <random N-bit value>

Uses the ISAAC-32 algorithm to generate random values between 0 and (1- (expt 2 N)). This function always consumes one or more ISAAC-32 words. Note that the N parameter is different from the CL random function parameter.

FAQ

Q) My Common Lisp implementation already uses the Mersenne Twister, what are the advantages of ISAAC?

A1) The Mersenne Twister is not a cryptographic PRNG. This means that it is possible for someone to predict future values based on previously observed values (just over 600 of them). As such, MT is particularly undesirable for things like web session IDs. You can still use MT for crypto, but you must use a cryptographic hash function on the MT output.

A2) cl-isaac appears to be roughly as fast as the Mersenne Twister #'random of CMUCL 19d on x86 before even considering the above-mentioned hash function overhead requirement of MT.

A3) cl-isaac is not implemented as an x86 VOP like CMUCL's Mersenne Twister, but instead in 100% standard ANSI Common Lisp (except for the kernel seed interface). This should mean comparable performance on all architectures targeted by your lisp compiler. The non-x86 MT implementation is apparently an order-of-magnitude slower.

Q) How "random" can I expect these values to be?

A) Very. From Bob Jenkins' website: "Cycles are guaranteed to be at least (expt 2 40) values long, and they are (expt 2 8295) values long on average. The results are uniformly distributed, unbiased, and unpredictable unless you know the seed. [...] Why not use RC4? RC4 is three times slower, more biased, has a shorter minimum and average cycle length, and is proprietary. No way is known to break either RC4 or ISAAC; both are immune to Gaussian elimination."

Note that there is a $1000 prize you can win from Jenkins if you find a flaw in ISAAC (but all flaws in CL-ISAAC are of course mine).

Initialize cryptographically strong self-seed starting with a kernel-seed as first round, and then performing a scramble on the bits and modular addition between the resulting values and a new kernel-seed on each additional count. :count n (default: 1), a real number, instructs the self-seed to repeat n times. If :is64 t, use ISAAC-64 context.