This document describes the Swarm random number library, an object oriented library of random number generators and accompanying distributions.
First, a few thoughts on pseudorandom number generation. It's hard to do right. There are many problems: the root cause, of course, is that computer algorithms themselves are not random. But there are also problems with defining "random", coming up with good tests for generators, and implementing algorithms correctly and efficiently. The history of pseudorandom number generation in simulation work is mostly embarassing. This library attempts to do a decent job of generating random numbers, as well as documenting how things work and what shortcomings there are. If you want to learn more about random number generation, the bibliography has useful notes. Knuth is the main reference in this realm, but too old to describe most of the particular generators used here.
The code here represents an effort to implement several efficient, reasonably safe generators. The algorithms come from reading the literature (see the bibliography): these algorithms have been implemented as accurately as possible and run through some simple tests. There is always a chance that some algorithm here is no good - there's also the chance that it is implemented incorrectly.
For best results, library users should test these generators yourself in some domain-specific way. One easy way to do this is to run an experiment twice: once with one class of generator (say, PMMLCG), and once with another (say, SWB). If the results differ radically, then you can suspect the generator. If they don't, well, the generator still might be faulty.
This is an object oriented random number library. There are two basic types of objects (described in protocols)
In the simplest case, you can instantiate one RandomBitGenerator and feed it to one RandomDistribution - this will duplicate your conventional libc random() function. (Note: the simtools library does exactly this, providing a uniformRandom object.)
But you can also do more powerful things: you can create multiple RandomBitGenerator objects to have independent streams of random numbers. You can feed several different RandomDistributions off of pne RandomBitGenerator. You have a lot of flexibility.
The Random library uses standard Objective C alloc/init style creation (not defobj createBegin/createEnd).
There are four base classes of random bit generators: PMMLCG, SWB, LCG, ACG. Of these, only SWB and PMMLCG are recommended for use: LCG and ACG are implemented for historical reasons. For each base class of generator, there are several particular classes with specific parameter settings for the generator. You should use these particular classes, not the base class.
Each random bit generator can be initialized in one of two ways-initSeed: (unsigned) seed;
-init;
getpid() * time(0)
at the moment.)
There are lots of other generators out there: Tauseworth generators, Wolfram's recommendation to use CA rule 30 to generate random bits, and a variety of functions from the cryptographic literature. In addition, any of these generators can be combined with a shuffler that somewhat breaks up the order of return values (this looks to be a good idea with PMMLCG1). Contributions to this library are welcome.
-(unsigned) rMax: (unsigned) max;
-(int) rMin: (int) min Max: (int) max;
-(float) rFloat;
-(double) rDouble;
-(unsigned char) bit;
In general, no test can say "yes this sequence is random". Several tests can say "no, it isn't", though. All of the algorithms implemented here are in published literature that claims that the algorithm passed some battery of tests: the tests in the support/random/tests directory are mostly there to debug the implementation. It would be a good idea for users of this library to run these tests and inspect the output.
Each program takes several test-specific arguments, as well as a particular argument which represents which generator to test. Run the test without arguments for help.
Implementing random number generators is a fairly difficult exercise in C hacking. Doing math correctly on all 2^32 integers is hard. In most cases, when choosing a tradeoff between speed and safety I've chosen safety. But in some cases, I haven't. In particular, in several generators (all but PMMLCG) I rely on math on unsigneds being exactly math modulo 2^32, including subtraction. In particular, I require things like
if (in real numbers) (a - b) < 0 then (in computer math) (a - b) is equivalent to (real numbers) (a - b + 2^32)
I think this is safe on all 32 bit unsigned ANSI C implementations. (ANSI specifies that unsigned arithmetic is done mod 2^n). If your machine doesn't have 32 bit unsigneds, this code definitely won't work. If you don't have two's complement arithmetic, it might not: best check it out.
As for performance, all of these generators are roughly the same speed (within 20% of each other), when compiled on a Sparc with 'gcc -O -mv8'. A quick test showed that these generators (called through Uniform: two message sends per random number) were a bit less than twice as slow as calling SunOS4.1.3 random() directly.