Random Library

Documentation and Implementation Status

Note: The new random library does not work in the same way as the old one. This means that some applications that

used the random library provided with the 1.0.2 release will be broken. However, porting these applications to the

new random library will be fairly easy since large efforts were made to adhere to the standard set with the last version

and some backwards compatibility hooks were incorporated.

Porting to Random 0.7

Overview

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 [See: $(SWARMHOME)/src/random/docs/SOURCES.for.0.7] 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:  $(SWARMHOME)/src/random/docs/SOURCES.for.0.7]:
         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 themselves 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.
There is also a tarball of test programs for the random number library on the Swarm
ftp site:
SwarmTests-0.7.tar.gz
(ftp://ftp2.santafe.edu/pub/swarm/RandomTests-0.7.tar.gz)

Documentation

The random library is defined and documented according to the Library Interface Conventions

(defobj/library.html)

. The following standard sections of documentation are available:

Interface Reference
(random/Interface.html)
Usage Guide
(random/UsageGuide.html)
Advanced Usage Guide
(random/AdvancedUsage.html)
Interface Design Notes
(random/InterfaceDesign.html)
Implementation Notes
(random/Implementation.html)

Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-10

Random Library: Documentation and Implementation Status

This is version 0.7 of Random.  It was donated by Sven Thommesen.  Version 0.6 was
a reimplementation of most of Nelson Minar's original random with many changes and
a new interface.  This version adds many
more generators and distributions and changes the interface somewhat.
The implementation may be a little unstable.  It hasn't been fully tested.  Sven has
also contributed a test suite which we will make available on the web site.  But,
as with any pseudo-random number generation library, results obtained from it should
be examined very closely.  But we are reasonably sure the generators and distributions
have been correctly implemented.

Documentation

More documentation is available within the Swarm source distribution, itself [Ref:
$(SWARMHOME)/src/random/docs/.  These docs consist of:
WHATS.NEW.in.0.7
                   Additions to Random since v.  0.6
WHATS.CHANGED.in.0.7
                   Changes to Random since v.  0.6
WHATS.LEFT.TODO
                   Improvements that may make it into v.  0.8
README.Generators.v07
                   Usage Guide for generator objects
README.Distributions.v07
                   Usage Guide for distribution objects
CHOOSING.A.GENERATOR
                   Notes on choosing a generator for your sim
DEFAULT.GENERATORS
                   Default generators invoked by distributions
SOURCES.for.0.7

Literature references for implemented objects
doc.generators.table
Summary descriptive data for generators
doc.generators.maxvalue
Values returned by [myGen getUnsignedSample]
doc.quality.generators
Results of statistical and timing tests
doc.timings
Timing results for generators and distributions
methods.SimpleGenerators.h
Methods implemented by a typical Simple generator
methods.SplitGenerators.h
Methods implemented by a typical Split generator

Anyone who attempts to generate random numbers by deterministic means is, of course,
living in a state of sin.  --Jon von Neuman

Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-08

Random Library: Porting to Random 0.7

The changes from version 0.6 to 0.7 consist mostly of a restructuring of the implementation
of the library.  However, there are some interface changes, as well, and the porting of applications
written to work with the 0.6 version might require changes to accomodate the new interface.
Also, it is advised that you take a look at the new interface, regardless of whether your application
compiles and runs with the new random because the old interface is deprecated and will eventually
be removed and because some of the functionality of the library changed such that the execution
of your application may differ.

Minimalist Porting Notes:

What is described here is the minimum a normal random user would have to change to get her
apps running with the 0.7.  For complete documentation of the changes made to the random library,
check the files:
$(SWARMHOME)/src/random/docs/WHATS.CHANGED.in.0.7
and
$(SWARMHOME)/src/random/docs/WHATS.NEW.in.0.7
         1.The 'magic numbers' used by setState/getState to identify generators and distributions
           have changed.  The sizes of the records returned by getState have also changed.
           Therefore version 0.7 generators will refuse to setStatea generator based on version
           0.6 data.
         2.The setState method has been renamed to setStateFrom, and getState to putStateInto.
         3.The verifySelf methods have been exorcised.  Their code has been moved to a separate
           test program.
         Marcus G. Daniels <mgd@santafe.edu>
         (mailto:mgd@santafe.edu)
         Last modified:  1998-01-26

Random Library: Interface Reference

The random library uses the module definition conventions
(../defobj/module.html)
established by the defobj library
(../defobj.html)
.  It also depends on standard supertypes and classes defined by this library.

Dependencies

Following are the other header files imported by <random.h>:
#import <defobj.h>
#import <random/generators.h>
#import <random/distributions.h>
#import <random/RandomDefs.h>
#import <random/RandomVars.h>
The defobj library interface is included to provide the basic object support.  Ran-
domDefs.h contains some C preprocessor macros and typedefs used in the library.

Object Types (with links to reference pages)

Contents:

The following shows the protocol inheritance trees and object definitions for generators
and distributions.  The complete set of methods implemented by these objects have
been subdivided into sub-protocols of methods that belong together logically.  Just
click on a (sub-)protocol name to see what methods it implements.  (You may want to
review the section on Protocols in the Objective-C book here!)
In the list below, any line that contains the word CREATABLE defines an object that
you can use in your program.  (This is part of the Swarm DefObj machinery.)  In other
words, while 'InternalState' is a normal protocol (a list of method definitions),
the name 'ACGgen' refers to both a protocol and a class that implements that protocol.
(You create an ACG generator by saying myGen = [ACGgen create:  ....]).  Similarly,
'GammaDist' defines both a protocol and a class that implements that protocol.
All generators and distributions ultimately inherit from SwarmObject.

The two files 'methods.SimpleGenerators.h' and 'methods.SplitGenerators.h' in directory
/random/docs show the complete sets of methods implemented for the two most common
types of generator.

Generators

InternalState
(Prot.html#InternalState)
SingleSeed
(Prot.html#SingleSeed)
MultiSeed
(Prot.html#MultiSeed)
Simple
(Prot.html#Simple)
SimpleOut
(Prot.html#SimpleOut)
SplitSingleSeed
(Prot.html#SplitSingleSeed)
SplitMultiSeed
(Prot.html#SplitMultiSeed)
Split
(Prot.html#Split)
SplitOut
(Prot.html#SplitOut)
SingleShortGenerator
(Prot.html#SingleShortGen)
<Create, Drop, InternalState, SimpleOut, Simple, SingleSeed>
SingleLongGenerator
(Prot.html#SingleLongGen)
<Create, Drop, InternalState, SimpleOut, Simple, SingleSeed, MultiSeed>
CombinedShortGenerator
(Prot.html#CombinedShortGen)
<Create, Drop, InternalState, SimpleOut, Simple, SingleSeed, MultiSeed>
CombinedLongGenerator
(Prot.html#CombinedLongGen)
<Create, Drop, InternalState, SimpleOut, Simple, SingleSeed, MultiSeed>
SingleShortSplitGenerator
(Prot.html#SingleShortSplitGen)
<Create, Drop, InternalState, SplitOut, Split, SplitSingleSeed>
SingleLongSplitGenerator

(Prot.html#SingleLongSplitGen)
<Create, Drop, InternalState, SplitOut, Split, SplitSingleSeed, SplitMultiSeed>
CombinedShortSplitGenerator
(Prot.html#CombinedShortSplitGen)
<Create, Drop, InternalState, SplitOut, Split, SplitSingleSeed, SplitMultiSeed>
CombinedLongSplitGenerator
(Prot.html#CombinedLongSplitGen)
<Create, Drop, InternalState, SplitOut, Split, SplitSingleSeed, SplitMultiSeed>
ACGgen
(ACGgen.html)
<SingleLongGenerator, CREATABLE>
C2LCGXgen
(C2LCGXgen.html)
<CombinedShortSplitGenerator, CREATABLE>
C2MRG3gen
(C2MRG3gen.html)
<CombinedLongGenerator, CREATABLE>
C2TAUSgen
(C2TAUS1-3gen.html)
<CombinedShortGenerator, CREATABLE>
  C2TAUS1gen
  (C2TAUS1-3gen.html#C2TAUS1gen)
  :  C2TAUSgen <C2TAUSgen, CREATABLE>
  C2TAUS2gen
  (C2TAUS1-3gen.html#C2TAUS2gen)
  :  C2TAUSgen <C2TAUSgen, CREATABLE>
  C2TAUS3gen
  (C2TAUS1-3gen.html#C2TAUS3gen)
  :  C2TAUSgen <C2TAUSgen, CREATABLE>
C3MWCgen
(C3MWCgen.html)
<CombinedLongGenerator, CREATABLE>
C4LCGXgen
(C4LCGXgen.html)
<CombinedShortSplitGenerator, CREATABLE>
LCGgen
(LCG1-3gen.html)
<SingleShortGenerator>
  LCG1gen
  (LCG1-3gen.html#LCG1gen)
  :  LCGgen <LCGgen, CREATABLE>

LCG2gen
(LCG1-3gen.html#LCG2gen)
:  LCGgen <LCGgen, CREATABLE>
LCG3gen
(LCG1-3gen.html#LCG3gen)
:  LCGgen <LCGgen, CREATABLE>
MRGgen
(MRG5-7gen.html)
<SingleLongGenerator>
MRG5gen
(MRG5-7gen.html#MRG5gen)
:  MRGgen <MRGgen, CREATABLE>
MRG6gen
(MRG5-7gen.html#MRG6gen)
:  MRGgen <MRGgen, CREATABLE>
MRG7gen
(MRG5-7gen.html#MRG7gen)
:  MRGgen <MRGgen, CREATABLE>
MT19937gen
(MT19937gen.html)
<SingleLongGenerator, CREATABLE>
MWCAgen
(MWCA-Bgen.html)
<SingleLongGenerator, CREATABLE>
MWCBgen
(MWCA-Bgen.html#MWCBgen)
<SingleLongGenerator, CREATABLE>
PMMLCGgen
(PMMLCG1-9gen.html)
<SingleShortGenerator>
PMMLCG1gen
(PMMLCG1-9gen.html#PMMLCG1gen)
:  PMMLCGgen <PMMLCGgen, CREATABLE>
PMMLCG2gen
(PMMLCG1-9gen.html#PMMLCG2gen)
:  PMMLCGgen <PMMLCGgen, CREATABLE>
PMMLCG3gen
(PMMLCG1-9gen.html#PMMLCG3gen)
:  PMMLCGgen <PMMLCGgen, CREATABLE>
PMMLCG4gen

(PMMLCG1-9gen.html#PMMLCG4gen)
:  PMMLCGgen <PMMLCGgen, CREATABLE>
PMMLCG5gen
(PMMLCG1-9gen.html#PMMLCG5gen)
:  PMMLCGgen <PMMLCGgen, CREATABLE>
PMMLCG6gen
(PMMLCG1-9gen.html#PMMLCG6gen)
:  PMMLCGgen <PMMLCGgen, CREATABLE>
PMMLCG7gen
(PMMLCG1-9gen.html#PMMLCG7gen)
:  PMMLCGgen <PMMLCGgen, CREATABLE>
PMMLCG8gen
(PMMLCG1-9gen.html#PMMLCG8gen)
:  PMMLCGgen <PMMLCGgen, CREATABLE>
PMMLCG9gen
(PMMLCG1-9gen.html#PMMLCG9gen)
:  PMMLCGgen <PMMLCGgen, CREATABLE>
PSWBgen
(PSWBgen.html)
<SingleLongGenerator, CREATABLE>
RWC2gen
(RWC28gen.html)
<SingleLongGenerator, CREATABLE>
RWC8gen
(RWC28gen.html#RWC8gen)
<CombinedLongGenerator, CREATABLE>
SCGgen
(SCGgen.html)
<SingleLongGenerator, CREATABLE>
SWBgen
(SWB1-3gen.html)
<SingleLongGenerator>
SWB1gen
(SWB1-3gen.html#SWB1gen)
:  SWBgen <SWBgen, CREATABLE>
SWB2gen
(SWB1-3gen.html#SWB2gen)
:  SWBgen <SWBgen, CREATABLE>
SWB3gen
(SWB1-3gen.html#SWB3gen)
:  SWBgen <SWBgen, CREATABLE>

TGFSRgen
(TGFSRgen.html)
<SingleLongGenerator>
  TT403gen
  (TGFSRgen.html#TT403gen)
  :  TGFSRgen <TGFSRgen, CREATABLE>
  TT775gen
  (TGFSRgen.html#TT775gen)
  :  TGFSRgen <TGFSRgen, CREATABLE>
  TT800gen
  (TGFSRgen.html#TT800gen)
  :  TGFSRgen <TGFSRgen, CREATABLE>

Distributions

ProbabilityDistribution
(Prot.html#ProbabilityDist)
<Create, Drop, InternalState>
BooleanDistribution
(Prot.html#BooleanDistribution)
<ProbabilityDistribution>
IntegerDistribution
(Prot.html#IntegerDistribution)
<ProbabilityDistribution>
UnsignedDistribution
(Prot.html#UnsignedDistribution)
<ProbabilityDistribution>
DoubleDistribution
(Prot.html#DoubleDistribution)
<ProbabilityDistribution>
Normal
(Prot.html#Normal)
<DoubleDistribution>
  RandomBitDist
  (RandomBitDist.html)
  <BooleanDistribution, CREATABLE>
BernoulliDist
(BernoulliDist.html)
<BooleanDistribution, CREATABLE>

UniformIntegerDist
(UniformIntegerDist.html)
<IntegerDistribution, CREATABLE>
UniformUnsignedDist
(UniformUnsignedDist.html)
<UnsignedDistribution, CREATABLE>
UniformDoubleDist
(UniformDoubleDist.html)
<DoubleDistribution, CREATABLE>
ExponentialDist
(ExponentialDist.html)
<DoubleDistribution, CREATABLE>
GammaDist
(GammaDist.html)
<DoubleDistribution, CREATABLE>
NormalDist
(NormalDist.html)
<Normal, CREATABLE>
LogNormalDist
(NormalDist.html#LogNormalDist)
<Normal, CREATABLE>

(../random.html)

(../random.html)

(UsageGuide.html)

Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-10

Random Library: Protocol Reference

InternalState
//
// InternalState --
//   Methods to save the internal state of an object (genera-
tor, distribution)
//   to a memory buffer allocated by the calling pro-
gram, and to set the state
//   of an object from previously saved state data, provided in a mem-
ory buffer.
//   Method -getStateSize specifies the minimum buffer size needed.
//
@protocol InternalState
- (unsigned) getStateSize; // size of buffer needed
- (void) putStateInto: (void *) buffer; // save state data for later use
- (void) setStateFrom: (void *) buffer; // set state from saved data
- (void) describe: (id) outStream; // prints ascii data to stream
- (char *)       getName; // returns name of object
- (unsigned) getMagic; // object's 'magic number'
@end

The InternalState protocol provides attributes common to the generators and distributions
provided in the random library.  This protocol could be used for any class of objects
that might contain an internal state, including things unrelated to pseudo random
number generation.
The "state" of a given object depends on the type of object it is.  In the case of
random, both the bit generators and the distributions are capable of carrying state.
The state is, in all cases, a structure that is understood by the object with which
it is associated.  The details of this structure can be found in the code for the
given generator or distribution; but, in general, the user is not expected to understand
the structure.  Where the state must be saved and used to restart, the user is expected
only to read and write the block of memory from and to the disk and pass the pointer
to and from the object with which the state is associated.  [See the Usage Guide
(./UsageGuide.html)
for examples of how to do this.]  Please note that different computer architectures
store binary data in memory in different ways (using different byte orders).  Since
this version of the InternalState protocol stores data in binary form, you cannot
expect to be able to use these methods to transfer data between different computers.
We hope to lift this restriction in a future version.
(unsigned) -getStateSize returns an unsigned integer indicating how many bytes of
memory are necessary to save the state of the object.

(void) -getState:  (void *) state writes a copy of the state of the object into the
memory address pointed to by the "state" pointer passed to it.  The memory should
be allocated before the message is sent.
(void) -setState:  (void *) state copies the values contained in the memory address
pointed to by "state" into the state variables used by the object.  The block of memory
containing the state may be sent back to the heap after the message has been sent.

(./Interface.html)

(./Interface.html)

These descriptions are not finished.  Please see the documentation in $(SWARMHOME)/src/random/docs/

Generator Protocols

SingleSeed
@deftype SingleSeed
CREATING
+  create: aZone setStateFromSeed: (unsigned) seed;
USING
- setStateFromSeed:  (unsigned)   seed;
- (unsigned) getMaxSeedValue;
- (unsigned)  getInitialSeed;
@end
MultiSeed
@deftype MultiSeed
CREATING
+ create: aZone setStateFromSeeds: (unsigned *) seeds;

USING
- setStateFromSeeds: (unsigned *) seeds;
- (unsigned)  lengthOfSeedVector;
- (unsigned *) getMaxSeedValues;
- (unsigned *)  getInitialSeeds;
@end
Simple
@deftype Simple
CREATING
+ createWithDefaults: aZone;
USING
- setAntithetic: (BOOL) antiT;
- (BOOL) getAntithetic;
- (unsigned long long int) getCurrentCount;
@end
SimpleOut
@deftype SimpleOut
USING
- (unsigned)     getUnsignedMax;
- (unsigned) getUnsignedSample;
- (float)        getFloatSample; // using 1 unsigned
- (double)       getThinDoubleSample; // using 1 unsigned
- (double)       getDoubleSample; // using 2 unsigneds
- (long double) getLongDoubleSample; // using 2 unsigneds
@end
SplitSingleSeed
@deftype SplitSingleSeed
CREATING
+ create: aZone
   setA: (unsigned) A  // # of virtual generators
   setv: (unsigned) v  // log2(#segments/generator)
   setw: (unsigned) w // log2(segment length)
setStateFromSeed: (unsigned) seed;
USING
- setStateFromSeed: (unsigned) seed;
- (unsigned) getMaxSeedValue;
- (unsigned) getInitialSeed;
@end
SplitMultiSeed
@deftype SplitMultiSeed
CREATING
+ create: aZone
   setA: (unsigned) A  // # of virtual generators
   setv: (unsigned) v  // log2(#segments/generator)

   setw: (unsigned) w // log2(segment length)
setStateFromSeeds: (unsigned *) seeds;
USING
- setStateFromSeeds: (unsigned *) seeds;
- (unsigned)  lengthOfSeedVector;
- (unsigned *) getMaxSeedValues; // min is 1
- (unsigned *) getInitialSeeds; // = getInitialSeeds: 0
@end
Split
@deftype Split
CREATING
+ createWithDefaults: aZone;
USING
- setAntithetic: (BOOL) antiT;
- (unsigned)     getNumGenerators; // returns A
- (unsigned)     getNumSegments; // returns v
- (unsigned)     getSegmentLength; // returns w
- (BOOL) getAntithetic;
- initGenerator:     (unsigned) vGen; // to segment #0
- restartGenerator: (unsigned) vGen; // start of current segment
- advanceGenerator: (unsigned) vGen; // to next segment
- jumpGenerator:     (unsigned) vGen  toSegment: (unsigned long long int) seg;
- initAll; // to segment #0
- restartAll; // start of current segment
- advanceAll; // to next segment
- jumpAllToSegment: (unsigned long long int) seg;
- (unsigned long long int) getCurrentCount:   (unsigned) vGen;
- (unsigned long long int) getCurrentSegment: (unsigned) vGen;
@end
SplitOut
@deftype SplitOut
USING
- (unsigned)     getUnsignedMax;
- (unsigned) getUnsignedSample:   (unsigned) vGen;
- (float)        getFloatSample:       (unsigned) vGen; // using 1 unsigned
- (double)       getThinDoubleSample: (unsigned) vGen; // using 1 unsigned
- (double)       getDoubleSample:      (unsigned) vGen; // using 2 unsigneds
- (long double) getLongDoubleSample: (unsigned) vGen; // using 2 unsigneds
@end
SingleShortGenerator
<Create, Drop, InternalState, SimpleOut, Simple, SingleSeed>
No extra messages added.
SingleLongGenerator
<Create, Drop, InternalState, SimpleOut, Simple, SingleSeed, MultiSeed>

No extra messages added.
CombinedShortGenerator
<Create, Drop, InternalState, SimpleOut, Simple, SingleSeed, MultiSeed>
No extra messages added.
CombinedLongGenerator
<Create, Drop, InternalState, SimpleOut, Simple, SingleSeed, MultiSeed>
No extra messages added.
SingleShortSplitGenerator
<Create, Drop, InternalState, SplitOut, Split, SplitSingleSeed>
No extra messages added.
SingleLongSplitGenerator
<Create, Drop, InternalState, SplitOut, Split, SplitSingleSeed, SplitMultiSeed>
No extra messages added.
CombinedShortSplitGenerator
<Create, Drop, InternalState, SplitOut, Split, SplitSingleSeed, SplitMultiSeed>
No extra messages added.
CombinedLongSplitGenerator
<Create, Drop, InternalState, SplitOut, Split, SplitSingleSeed, SplitMultiSeed>
No extra messages added.

Distribution Protocols

ProbabilityDistribution
<Create, Drop, InternalState>
// ProbabilityDistribution --
//
// A process for generating a sequence of random numbers matching the
//   frequencies defined by a specific distribution function.  The
//   process is driven by input from a supplied uniform random generator.
//
@deftype ProbabilityDistribution <Create, Drop, InternalState>
CREATING
+ createWithDefaults: aZone;
+ create: aZone setGenerator: (id) generator;
+ create: aZone setGenerator: (id) generator
setVirtualGenerator: (unsigned) vGen;
+ createBegin;
USING

- setGenerator: (id) generator;
- setGenerator: (id) generator
setVirtualGenerator: (unsigned) vGen;
- createEnd;
- reset;
-                 getGenerator;
- (unsigned) getVirtualGenerator;
- (BOOL) getOptionsInitialized;
- (unsigned long long int) getCurrentCount;
@end
BooleanDistribution
<ProbabilityDistribution>
//
// BooleanDistribution --
//   A probability distribution that returns YES/NO sample values.
//
@deftype BooleanDistribution <ProbabilityDistribution>
- (BOOL) getBooleanSample;
- (int) getIntegerSample; // for convenience
@end
IntegerDistribution
<ProbabilityDistribution>
//
// IntegerDistribution --
//   A probability distribution that returns integer sample values.
//
@deftype IntegerDistribution <ProbabilityDistribution>
- (int) getIntegerSample;
@end
UnsignedDistribution
<ProbabilityDistribution>
//
// UnsignedDistribution --
//   A probability distribution that returns non-
negative integer sample values.
//
@deftype UnsignedDistribution <ProbabilityDistribution>
- (unsigned) getUnsignedSample;
@end
DoubleDistribution
<ProbabilityDistribution>
//
// DoubleDistribution --
//   A probability distribution that returns an approximation of continuous

//   values as represented by double-precision floating point values.
//
@deftype DoubleDistribution <ProbabilityDistribution>
- (double) getDoubleSample;
@end
Normal
<DoubleDistribution>
//
// NormalDistribution -- a well-known continuous probability distribution
// LogNormalDistribution -- also well-known ...
//
@deftype Normal <DoubleDistribution>
CREATING
+ create: aZone setGenerator: generator
                  setMean: (double) mean setVariance: (double) variance;
+ create: aZone setGenerator: generator
setVirtualGenerator: (unsigned) vGen
                  setMean: (double) mean setVariance: (double) variance;
USING
- setMean: (double) mean setVariance: (double) variance;
- (double) getMean;
- (double) getVariance;
- (double) getStdDev;
- (double) getSampleWithMean: (double) mean
withVariance: (double) variance;
@end

(./Interface.html)

Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-26

ACGgen Class

//
// ACGgen--
//   predefined random number generators, not recommended for serious use;
//   included for historical reasons (compatibility with earlier releases).
//
@protocol ACGgen       <SingleLongGenerator, CREATABLE> @end

Use of this generator is NOT Recommended

Documentation

Generator name:  | ACG
Description:  | Additive Congruential Generator
Reference:  | ACG is an often used algorithm, mentioned in Knuth,
| Numerical Recipes, etc.
| state vector = f(seed)
Algorithm:  | state_n = (state_(n-s) + state_(n-r)) mod 2^32; r > s
| output = state_n
| ACG is in the Lagged Fibonacci class of generators.
| These generators use a basic algorithm of the form
| X_n = f(X_(n-r),X_(n-s)) mod m; r>s
| The function f is typically xor, addition, subtraction,
| multiplication or subtraction with carry. It uses
| simpler math than a basic LCG, but keeps a larger state.
Comments:  | This generator relies on controlled overflow at 32 bits.
| This requires that unsigned be a 32bit value that follows
| ANSI C rules.
Implementation:  | The state vector contains the generator's r most recent
| outputs (X_n .. X_(n-r)). This vector is initialized from
| an LCG generator using one 32-bit seed value. After
| initialization we throw away r*5 numbers to 'prime' the
| generator (i.e. make sure we have entered a closed cycle.)

Parameters:  | unsigned int r // long lag
| unsigned int s // short lag
State:  | unsigned int state[r] // state vector
Output types:  | unsigned int (we return the current state).
| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.
| (See the implementation file for more details.)
Output range:  | Any number in the range [0,2^32-1] may be returned
| (i.e. [0,4294967295].)
Valid seeds:  | Using create:setStateFromSeed:  [1,2^32-1]
| Using create:setStateFromSeeds: [1,2^32-2]
Cycles:  | With properly chosen parameters, these generators
| have a cycle of length about 2^r.
Output Quality:  | Low order bits are poor, and there are other problems.
| SWB is a better generator in the same class, and it is
| only slightly slower.
Reference for | Knuth, op.cit.
output quality:  |
ACGgen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                          2.702 uS
|   -getFloatSample, getDoubleSample:          4.482 uS
|   -getFatDoubleSample, getLongDoubleSample: 8.299 uS
Relative speed:
| Speed 1.369 (time 0.731) relative to MT19937 getUnsignedSample
--------------- | -----------------------------------------------------------
---
Parameters:  | r = 55
| s = 24
Reference for | These values recommended by Knuth.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length ~ 2^r.
Output Quality:  | Low-order bits are poor.

          Reference for | Knuth, op.cit.
          output quality:  |

(./Interface.html)

(./Interface.html)

(./C2LCGXgen.html)

         Marcus G. Daniels <mgd@santafe.edu>
         (mailto:mgd@santafe.edu)
         Last modified:  1998-01-26

C2LCGXgen Class

//
// C2LCGX --
//   short component based generator with splitting facilities. Recommended.
//
@deftype C2LCGXgen  <CombinedShortSplitGenerator, CREATABLE> @end

Documentation

Generator name:  | C2LCGX
Description:  | Combined random generator using 2 (PMM)LGC generators
Reference:  | Pierre L'Ecuyer and Serge Cote,
| "Implementing a Random Number Package with Splitting
| Facilities." ACM Transactions on Mathematical Software
| vol. 17 no. 1, March 1991, pp. 98-111.
| Their name for the generator: 'split.c'.
| See also <http://www.iro.umontreal.ca/~lecuyer>.
Comments:  | This portable generator is based on a backbone generator
| which is a combination of 2 (PMM)LCG generators. It has a
| period length of almost 2^61 (2.3e18).
| The backbone generator's period can be split up into a
| number of 'virtual generators' (A), each of which can be set
| to access a number of 'segments' (V) of length W, subject to
| the constraint that A * V * W <= 2^60.
| This is possible because the backbone generator has
| 'jump-ahead facilities' -- i.e. a quick method of calculating
| the state of the generator at a given point in its cycle
| without having to actually draw a large number of variates.
Algorithm | state(j) = seed(j)
for each | newstate(j) = (a(j) * oldstate(j)) mod m(j)
generator:  | output(j) = state(j)
Algorithm | output = (state(1) - state(2)) mod m(0)
for combination:|

Comments:  | For a discussion of PMMLCG generators, see the source file
| PMMLCGgen.h.
Configuration | unsigned int numGenerators; // # virtual generators
parameters:  | unsigned int numSegments; // log2(#segments/vGen)
| unsigned int segmentLength; // log2(segment length)
State:  | unsigned int state [numGenerators] [2];
| (each virtual generator has a 4-integer state vector)
Output types | unsigned int in [0,unsignedMax].
(for each | float in [0.0,1.0) using 1 iteration of the generator.
virtual | double in [0.0,1.0) using 1 or 2 iterations of the generator.
generator):  | long double in [0.0,1.0) using 2 iterations of the generator.
Output range:  | The combined generator yields output in the range [0,m0-1]
| (i.e. [0,2147483562].)
Limits on | Number of generators A <= 2^25  (33,554,432)
parameters:  | (You'll likely run out of memory before then ...)
| Number of segments / generator <= 2^60 (i.e. v <= 60)
| Length of each segment <= 2^60 (i.e. w <= 60)
Defaults:  | A=32, v=20, w=30
Valid seeds:  | Using create:setStateFromSeed: in [1, 2^32-1]
| Using create:setStateFromSeeds:
| The generator must be seeded with 2 starting seeds:
|  Seed[0]: [1, 2147483562] = [1,m1-1]
|  Seed[1]: [1, 2147483398] = [1,m2-1]
Cycles:  | With properly chosen parameters, the component generators
| have a single full cycle of length (m-2).
| The combined generator has a cycle length of
| (m1-1)*(m2-1)/2 = 2147483562*2147483398/2 ~= 2^61.
Output Quality:  | All bits should be safe.
| The combined generator has much better statistical
| properties than either of its component PMMLCG's.
Reference for | L'Ecuyer and Cote, op. cit.
output quality:  |
Implementation  | The code for -getUnsignedMax uses a trick devised by
comment:         | Schrage to avoid 32-bit overflow when calculating the
| next state (i.e. using q=m/a and r=m%a as auxiliary
| values). Using 64-bit math (long long integers) is more

| straightforward. Unfortunately, on x86 at least, there is
| a significant speed penalty for doing so.
| The output, however, would be identical. YMMV.
C2LCGXgen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                           7.029 uS
|   -getFloatSample, getDoubleSample:           9.049 uS
|   -getFatDoubleSample, getLongDoubleSample: 16.725 uS
Relative speed:
| Speed 0.526 (time 1.900) relative to MT19937 getUnsignedSample
--------------- . -----------------------------------------------------------
--
Parameters:  | a[COMPONENTS] = {  40014,       40692 }
| m[COMPONENTS] = { 2147483563, 2147483399 }
Reference for | L'Ecuyer and Cote, op. cit.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length close to 2^60 (2.3e18).
Output Quality:  | The authors performed an exhaustive search for component
| generators that would yield the best statistical quality.
Reference for | L'Ecuyer and Cote, op. cit.
output quality:  |

(./ACGgen.html)

(./Interface.html)

(./C2MRG3gen.html)

Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-26

C2MRG3gen Class

//
// C2MRG3 --
//   long component based generator recommended for use.
//
@deftype C2MRG3gen <CombinedLongGenerator, CREATABLE> @end

Documentation

Generator name:  | C2MRG3
Description:  | Combination of 2 Multiple Recursive LCG Generators
Reference:  | Pierre L'Ecuyer,
| "Combined Multiple Recursive Random Number Generators."
| See <http://www.iro.umontreal.ca/~lecuyer>.
| For a discussion of MRG generators, see MRGgen.h.
Algorithm:  | For each generator:
| x_n = (a_1*x_n-1 + a_2*x_n-2 ... + a_k*x_n-k) mod m
| Combining them:
| x = (x1 - x2) mod m1
Comments:  | Combinations of like generators are shown to have better
| statistical properties than single generators.
Implementation:  | The components of this generator each has two nonzero
| multipliers (and one that's zero). They use different
| moduli (2^31-1, 2145483479.)
Parameters:  | unsigned int m[2] // modulus
| unsigned int a1[2], ak[2] // multipliers
| unsigned int k[2] // the order of the generator
State:  | unsigned int x[k][2] // state vector
Output types:  | unsigned int (we return the current state).
| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.

| (See the implementation file for more details.)
Output range:  | Any number in the range [0,unsignedMax] = [0,m1-2].
Valid seeds:  | This generator requires 3 seeds for each component:
| within [1,m1-1] for component 1;
| within [1,m2-1] for component 2.
| Using create:setStateFromSeed: in [1,2^32-1]
Cycles:  | With properly chosen parameters, this generator
| has a single cycle of length (m1^3-1)(m2^3-1)/2
| or 2^184 < cycle < 2^185 (4.9e55).
Output Quality:  | Good.
Reference for | L'Ecuyer et al, op. cit.
output quality:  |
C2MRG3gen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                          13.459 uS
|   -getFloatSample, getDoubleSample:          15.203 uS
|   -getFatDoubleSample, getLongDoubleSample: 29.699 uS
Relative speed:
| Speed 0.275 (time 3.640) relative to MT19937 getUnsignedSample
--------------- . -----------------------------------------------------------
--
Parameters:  | unsigned int k = 3 // lag order
| unsigned int m1 = 2^31 - 1 // modulus
| unsigned int a12 = 63308 // multiplier
| unsigned int a13 = -183326 // multiplier
| unsigned int m2 = 2145483479 // modulus
| unsigned int a21 = 86098 // multiplier
| unsigned int a23 = -539608 // multiplier
Reference for | L'Ecuyer et al, op. cit., Table 3.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length
| ((2^31-1)^3 - 1) * (2145483479^3 - 1) / 2 ~= 4.89e55,
| i.e. 2^184 < cycle < 2^185.
| (The paper, in apparent error, claims
| that the cycle is close to 2^205.)

          Output Quality:  | Good. Parameters chosen on the basis of theory
          | and empirical testing.
          Reference for | L'Ecuyer et al, op. cit.
          output quality:  |

(./C2LCGXgen.html)

(./Interface.html)

(./C2TAUS1-3gen.html)

         Marcus G. Daniels <mgd@santafe.edu>
         (mailto:mgd@santafe.edu)
         Last modified:  1998-01-26

C2TAUSgen Class

//
// C2TAUS1, C2TAUS2, C2TAUS3 --
//   short component based generator recommended for use.
//
@deftype C2TAUSgen     <CombinedShortGenerator> @end
@deftype C2TAUS1gen   <C2TAUSgen, CREATABLE> @end
@deftype C2TAUS2gen   <C2TAUSgen, CREATABLE> @end
@deftype C2TAUS3gen   <C2TAUSgen, CREATABLE> @end

General Documentation

Generator name:  | C2TAUS
Description:  | Combined Tausworthe Generator
| based on 2 component generators of periods 2^31-1 and 2^29-1
Reference:  | Shu Tezuka and Pierre L'Ecuyer,
| "Efficient and Portable Combined Tausworthe
| Random Number Generators."
| ACM Transactions on Modeling and Computer Simulation,
| vol. 1 no. 2, April 1991, pp. 99-112.
| Original reference for the Tausworthe algorithm:
| R. C. Tausworthe, "Random Numbers Generated by Linear
| Recurrence modulo 2", Math. Comput. 19 (1965), 201-209.
Algorithm:  | state = seed, then:
(Each | b = ((old << Q) ^old) & mask
component:)  | new = ((old << S) ^(b >> (P-S)) & mask
(Combination:)  | output = ((new1 ^(new2 << (P1-P2))
Implementation:  |
Parameters:  | int   P [2] // word length
| int   Q [2] //
| int   S [2] //
| int PmS [2] // P - S
| int P1mP2 // P[0] - P[1]

| unsigned int Mask[2] // 2^P - 1
State:  | unsigned int state[2] // state vector
Output types:  | unsigned int (we return the current state).
| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.
| (See the implementation file for more details.)
Output range:  | Any number in the range [0,2^31-1] may be returned
| (i.e. [0,2147483647].)
Valid seeds:  | Using create:setStateFromSeed: in [1, 2^32-1]
| Using create:setStateFromSeeds:
|  Seed[0] must be in [1,Mask[0]];
|  Seed[1] must be in [1,Mask[1]];
Cycles:  | These generators have a single full cycle
| of length Mask1 * Mask2 ~= 2^60 (1.15e18).
Output Quality:  | The authors conducted an exhaustive search among candidate
| Tausworthe generators to find the combination that had the
| best lattice structure. (Single Tausworthe generators do not
| have acceptable properties.) The 3 generators implemented
| here were retained as the best found.
Reference for | Tezuka and L'Ecuyer, op. cit.
output quality:  |
C2TAUSgen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                           4.078 uS
|   -getFloatSample, getDoubleSample:           5.932 uS
|   -getFatDoubleSample, getLongDoubleSample: 10.920 uS
Relative speed:
| Speed 0.907 (time 1.103) relative to MT19937 getUnsignedSample

C2TAUS1gen Documentation

Parameters:  | P = 31 so Mask = 2^31-1
(component 1) | S = 12 so PmS = 19
| Q = 13
| P = 29 so Mask = 2^29-1
(component 2) | S = 17 so PmS = 12

| Q =  2
Reference for | These values recommended by Tezuka and L'Ecuyer,
parameters:  | op. cit., table I p. 107.
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length ~ 2^60.
Output Quality:  | Good.
Reference for | Tezuka and L'Ecuyer, op.cit.
output quality:  |

C2TAUS2gen Documentation

Parameters:  | P = 31 so Mask = 2^31-1
(component 1) | S = 21 so PmS = 10
| Q =  3
| P = 29 so Mask = 2^29-1
(component 2) | S = 17 so PmS = 12
| Q =  2
Reference for | These values recommended by Tezuka and L'Ecuyer,
parameters:  | op. cit., table II p. 107.
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length ~ 2^60.
Output Quality:  | Good.
Reference for | Tezuka and L'Ecuyer, op.cit.
output quality:  |

C2TAUS3gen Documentation

Parameters:  | P = 31 so Mask = 2^31-1
(component 1) | S = 13 so PmS = 18
| Q = 13
| P = 29 so Mask = 2^29-1
(component 2) | S = 20 so PmS =  9
| Q =  2
Reference for | These values recommended by Tezuka and L'Ecuyer,

parameters:  | op. cit., table III p. 107.
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length ~ 2^60.
Output Quality:  | Good.
Reference for | Tezuka and L'Ecuyer, op.cit.
output quality:  |

(./C2MRG3gen.html)

(./Interface.html)
(./C3MWCgen.html)
Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-26

C3MWCgen Class

//
// C3MWC --
//   long component based generator recommended for use.
//
@deftype C3MWCgen   <CombinedLongGenerator, CREATABLE> @end

Documentation

Generator name:  | C3MWC
Description:  | Combined Multiply-With-Carry generator
Reference:  | Article posted to Usenet in 1994 by George Marsaglia,
| "The Mother of all Random Number Generators."
| Source found at <ftp://ftp.taygeta.com/pub/c/mother.c>
| Also document /papers/mwc1.ps on his Diehard CD-ROM,
| found at <http://www.hku.hk/internet/randomCD.html>.
Algorithm:  | K = a * (K & 65535) + (K>>16);
| J = b * (J & 65535) + (J>>16);
| I = c * (I & 65535) + (I>>16);
| L = d * (L & 65535) + (L>>16);
| M = e * (M & 65535) + (M>>16);
| N = f * (N & 65535) + (N>>16);
| return ((K+I+M)>>16) + (J+L+N);
Comments:  | This generator is a combination of 3 MWC generators,
| each of which is a combination of 2 16-bit
| Multiply-With-Carry generators.
Parameters:  | unsigned int a = 30903 // multiplier
| unsigned int b = 18000
| unsigned int c = 29013
| unsigned int d = 30345
| unsigned int e = 30903
| unsigned int f = 31083
State:  | unsigned int K,J,I,L,M,N // state vector
Output types:  | unsigned int (we return the current state).

| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.
| (See the implementation file for more details.)
Output range:  | Any number in the range [0,unsignedMax] = [0,2^32-1].
Valid seeds:  | Using create:setStateFromSeed:  [1, 2^32-1]
| Using create:setStateFromSeeds: each component may have
| a 'state' <= 0xffff and a carry <= (multiplier-1), so that
| for the first component the largest seed allowed is
| (a-1)<<16 + 65535.
Cycles:  | This generator is claimed to be strictly periodic, with a
| period > 2^118. There may be more than one cycle.
Output Quality:  | Good.
Reference for | Marsaglia, op. cit.
output quality:  |
C3MWCgen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                           6.437 uS
|   -getFloatSample, getDoubleSample:           8.200 uS
|   -getFatDoubleSample, getLongDoubleSample: 15.562 uS
Relative speed:
| Speed 0.574 (time 1.741) relative to MT19937 getUnsignedSample
--------------- . -----------------------------------------------------------
--

(./C2TAUS1-3gen.html)

(./Interface.html)

(./C4LCGXgen.html)

Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-26

C4LCGXgen Class

//
// C4LCGXgen --
//   short component based generator with splitting facilities. Recommended.
//
@deftype C4LCGXgen  <CombinedShortSplitGenerator, CREATABLE> @end

Documentation

Generator name:  | C4LCGX
Description:  | Combined random generator using 4 (PMM)LGC generators
Reference:  | Pierre L'Ecuyer and Terry H. Andres,
| "A Random Number Generator Based on the Combination
|  of Four LCGs", 17 December 1996.
| To appear in Mathematics and Computers in Simulation. See:
| <http://www.iro.umontreal.ca/~lecuyer/myftp/papers/clcg4.ps>.
| Their name for the generator: 'clcg4'.
Comments:  | This portable generator is based on a backbone generator
| which is a combination of 4 (PMM)LCG generators. It has a
| period length of (m1-1)(m2-1)(m3-1)(m4-1) / 8, or almost
| 2^121 (2.6e36).
| The backbone generator's period can be split up into a
| number of 'virtual generators' (A), each of which can be set
| to access a number of 'segments' (V) of length W, subject to
| the constraint that A * V * W <= 2^120.
| This is possible because the backbone generator has
| 'jump-ahead facilities' -- i.e. a quick method of calculating
| the state of the generator at a given point in its cycle
| without having to actually draw a large number of variates.
Algorithm | state(j) = seed(j)
for each | newstate(j) = (a(j) * oldstate(j)) mod m(j)
generator:  | output(j) = state(j)
Algorithm | output = (state(1) - state(2) + state(3) - state(4)) mod m(0)
for combination:|

Comments:  | For a discussion of PMMLCG generators, see the source file
| PMMLCGgen.h.
Configuration | unsigned int numGenerators; // # virtual generators
parameters:  | unsigned int numSegments; // log2(#segments/vGen)
| unsigned int segmentLength; // log2(segment length)
State:  | unsigned int state [numGenerators] [4];
| (each virtual generator has a 4-integer state vector)
Output types | unsigned int in [0,unsignedMax].
(for each | float in [0.0,1.0) using 1 iteration of the generator.
virtual | double in [0.0,1.0) using 1 or 2 iterations of the generator.
generator):  | long double in [0.0,1.0) using 2 iterations of the generator.
Output range:  | The combined generator yields output in the range [0,m0-2]
| (i.e. [0,2147483645].)
Limits on | Number of generators A <= 2^25  (33,554,432)
parameters:  | (You'll likely run out of memory before then ...)
| Number of segments / generator <= 2^63 (i.e. v<=63)
| Length of each segment <= 2^63 (i.e. w<=63)
Defaults:  | A=128, v=31, w=41
Valid seeds:  | Using create:setStateFromSeed: in [1, 2^32-1]
| Using create:setStateFromSeeds:
| The generator must be seeded with 4 starting seeds:
|  Seed[0]: [1, 2147483646] = [1,m1-1]
|  Seed[1]: [1, 2147483542] = [1,m2-1]
|  Seed[2]: [1, 2147483422] = [1,m3-1]
|  Seed[3]: [1, 2147483322] = [1,m4-1]
Cycles:  | With properly chosen parameters, the component generators
| have a single full cycle of length (m-1).
| The combined generator has a cycle length of
| 2147483646*2147483542*2147483422*2147483322/8 > 2^120.
Output Quality:  | All bits should be safe.
| The combined generator has much better statistical
| properties than either of its component PMMLCG's.
Reference for | L'Ecuyer and Andres, op. cit.
output quality:  |
Implementation  | The code for -getUnsignedMax uses a trick devised by

comment:         | Schrage to avoid 32-bit overflow when calculating the
| next state (i.e. using q=m/a and r=m%a as auxiliary
| values). Using 64-bit math (long long integers) is more
| straightforward. Unfortunately, on x86 at least, there is
| a significant speed penalty for doing so.
| The output, however, would be identical. YMMV.
C4LCGXgen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                          11.688 uS
|   -getFloatSample, getDoubleSample:          13.644 uS
|   -getFatDoubleSample, getLongDoubleSample: 26.154 uS
Relative speed:
| Speed 0.316 (time 3.160) relative to MT19937 getUnsignedSample
--------------- | -----------------------------------------------------------
---
Parameters:  | a[COMPONENTS] = {  45991,      207707,
|       138556,       49689 }
| m[COMPONENTS] = { 2147483647, 2147483543,
|  2147483423, 2147483323 }
Reference for | L'Ecuyer and Andres, op. cit.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length close to 2^121 (2.6e36).
Output Quality:  | The authors performed an exhaustive search for component
| generators that would yield the best statistical quality.
Reference for | L'Ecuyer and Andres, op. cit.
output quality:  |

(./C3MWCgen.html)

(./LCG1-3gen.html)
Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-26

LCG1-3gen Classes

//
// LCG1, LCG2, LCG3 --
//   single short random number generators,
//   NOT recommended for serious use; these are included for
//   historical reasons (compatibility with earlier releases).
//
@deftype LCGgen       <SingleShortGenerator> @end
@deftype LCG1gen         <LCGgen, CREATABLE> @end
@deftype LCG2gen         <LCGgen, CREATABLE> @end
@deftype LCG3gen         <LCGgen, CREATABLE> @end

Use of these generators is NOT Recommended

General Documentation

Generator name:  | LCG
Description:  | Linear Congruential Generator
Reference:  | This is a classic generator.
| See for example Donald Knuth,
| The Art of Computer Programming,
| vol. II, "Seminumerical Algorithms."
| state = seed
Algorithm:  | newstate = ((a * oldstate) + c ) mod 2^32
| output = state
Comments:  | This generator relies on controlled overflow at 32 bits.
| This requires that unsigned be a 32bit value that follows
| ANSI C rules.
| Knuth claims that the adder c does not matter much, as
| long as it has no factors in common with the modulus 2^32.

Parameters:  | unsigned int c // adder
| unsigned int a // multiplier

State:  | unsigned int state // a "state vector" of length 1
Output types:  | unsigned int (we return the current state).
| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.
| (See the implementation file for more details.)
Output range:  | Any number in the range [0,2^32-1] may be returned
| (i.e. [0,4294967295].)
Valid seeds:  | Using create:setStateFromSeed:  [1,2^32-1]
| Using create:setStateFromSeeds: [1,2^32-1]
Cycles:  | With properly chosen parameters, these generators
| have a single full cycle of length (2^32).
Output Quality:  | Low order bits are poor.
Reference for | Knuth, op.cit.
output quality:  |
LCGgen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                          2.564 uS
|   -getFloatSample, getDoubleSample:          4.295 uS
|   -getFatDoubleSample, getLongDoubleSample: 7.734 uS
Relative speed:
| Speed 1.442 (time 0.693) relative to MT19937 getUnsignedSample

LCG1gen Documentation

Parameters:  | a =      1,664,525
| c = 1,013,904,223
Reference for | The multiplier is from Knuth vol II (line 26 of table).
parameters:  | Adder is from Numerical Recipes, in turn from H.W.Lewis
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length m.
Output Quality:  | Low-order bits are poor.
Reference for | Knuth, op.cit. and Numerical Recipes.
output quality:  |

LCG2gen Documentation

Parameters:  | a =         69,069
| c = 1,013,904,223
Reference for | The multiplier is from Knuth vol II (line 25 of table).
parameters:  | Adder is from Numerical Recipes, in turn from H.W.Lewis
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length m.
Output Quality:  | Low-order bits are poor.
Reference for | Knuth, op.cit. and Numerical Recipes.
output quality:  |

LCG3gen Documentation

Parameters:  | a =   1,664,525
| c = 152,193,325
Reference for | The multiplier is from Knuth vol II (line 26 of table).
parameters:  | Adder is from Numerical Recipes, in turn from H.W.Lewis
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length m.
Output Quality:  | Low-order bits are poor.
Reference for | Knuth, op.cit. and Numerical Recipes.
output quality:  |

(./C4LCGXgen.html)

(./MRG5-7gen.html)
Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-26

MRG5-7gen Classes

//
// MRG5, MRG6, MRG7 --
//   single long generators recommended for use.
//
@deftype MRGgen       <SingleLongGenerator>  @end
@deftype MRG5gen       <MRGgen, CREATABLE> @end
@deftype MRG6gen       <MRGgen, CREATABLE> @end
@deftype MRG7gen       <MRGgen, CREATABLE> @end

General Documentation

Generator name:  | MRG
Description:  | Multiple Recursive LCG Generator
Reference:  | Pierre L'Ecuyer, Francois Blouin and Raymond Couture,
| "A Search for Good Multiple Recursive Random Generators."
| See <http://www.iro.umontreal.ca/~lecuyer>.
Algorithm:  | x_n = (a_1*x_n-1 + a_2*x_n-2 ... + a_k*x_n-k) mod m
Comments:  | These generators require k multipliers and k past values
| to be kept. In their paper, the authors investigate MRG's
| of order k from 1 to 7. They provide several sets of
| parameters which they recommend out of a large number that
| were tested. Generally, the quality of the generators
| increases with k.
Implementation:  | The authors discovered that most of the benefit of these
| generators can be had if only a_1 and a_k are nonzero and the
| rest zero; this yields faster execution since only 2 terms
| need be calculated. We implement 4 such generators here,
| all with modulus m close to 2^31.

Parameters:  | unsigned int m // modulus
| unsigned int a1, ak // multipliers
| unsigned int k // the order of the generator
State:  | unsigned int x[k] // state vector

Output types:  | unsigned int (we return the current state).
| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.
| (See the implementation file for more details.)
Output range:  | Any number in the range [0,unsignedMax] = [0,m-2].
Valid seeds:  | Using create:setStateFromSeed:  [1, 2^32-1]
| Using create:setStateFromSeeds: [1, unsignedMax]
| (unsignedMax differs between MRG5, MRG6, MRG7)
Cycles:  | With properly chosen parameters, these generators
| have a single cycle of length m^k - 1.
| Thus, for m ~= 2^31 we have:
| k=5 => cycle ~= 2^155,
| k=6 => cycle ~= 2^186,
| k=7 => cycle ~= 2^217.
Output Quality:  | Good.
Reference for | L'Ecuyer et al, op. cit.
output quality:  |
MRG5gen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                           9.674 uS
|   -getFloatSample, getDoubleSample:          11.524 uS
|   -getFatDoubleSample, getLongDoubleSample: 22.135 uS
Relative speed:
| Speed 0.382 (time 2.616) relative to MT19937 getUnsignedSample
--------------- . -----------------------------------------------------------
--
MRG6gen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                          10.449 uS
|   -getFloatSample, getDoubleSample:          12.337 uS
|   -getFatDoubleSample, getLongDoubleSample: 27.735 uS
Relative speed:
| Speed 0.354 (time 2.826) relative to MT19937 getUnsignedSample
--------------- . -----------------------------------------------------------
--
MRG7gen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                          10.913 uS

|   -getFloatSample, getDoubleSample:          12.764 uS
|   -getFatDoubleSample, getLongDoubleSample: 24.627 uS
Relative speed:
| Speed 0.339 (time 2.951) relative to MT19937 getUnsignedSample

MRG5gen Documentation

Parameters:  | unsigned int k = 5 // lag order
| unsigned int m = 2^31 - 1 // modulus
| unsigned int a1 = 107374182 // multiplier
| unsigned int a5 = 104480 // multiplier
Reference for | L'Ecuyer et al, op. cit., Table 3.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length (2^31-1)^5 - 1,
| i.e. 2^154 < cycle < 2^155.
Output Quality:  | Good. Parameters chosen on the basis of theory
| and empirical testing.
Reference for | L'Ecuyer et al, op. cit.
output quality:  |

MRG6gen Documentation

Parameters:  | unsigned int k = 6 // lag order
| unsigned int m = 2^31 - 1 // modulus
| unsigned int a1 = 177786 // multiplier
| unsigned int a6 = 64654 // multiplier
Reference for | L'Ecuyer et al, op. cit., Table 3.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length (2^31-1)^6 - 1,
| i.e. 2^185 < cycle < 2^186.
Output Quality:  | Good. Parameters chosen on the basis of theory
| and empirical testing.
Reference for | L'Ecuyer et al, op. cit.
output quality:  |

MRG7gen Documentation

Parameters:  | unsigned int k = 7 // lag order
| unsigned int m = 2^31 - 19 // modulus
| unsigned int a1 = 1071064 // multiplier
| unsigned int a7 = 2113664 // multiplier
Reference for | L'Ecuyer et al, op. cit., Table 3.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length (2^31-1)^7 - 1,
| i.e. 2^216 < cycle < 2^217.
Output Quality:  | Good. Parameters chosen on the basis of theory
| and empirical testing.
Reference for | L'Ecuyer et al, op. cit.
output quality:  |

(./LCG1-3gen.html)

(./Interface.html)

(./MT19937gen.html)

Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-26

MT19937gen Class

//
// MT19937 --
//   single *very* long generator recommended for use.
//
@deftype MT19937gen  <SingleLongGenerator, CREATABLE> @end

Documentation

Generator name:  | MT19937
Description:  | Twisted GFSR generator
Reference:  | Makoto Matsumoto and ??? Nishimura,
| code posted to the pLab web site, xx/xx/97.
| Site: <http://random.mat.sbg.ac.at>
| Code: <ftp://random.mat.sbg.ac.at/pub/data/mt19937b-int.c>
| Article reportedly submitted to ACM TOMACS.
|
Algorithm:  |
|
Comments:  |
Implementation:  |
Parameters:  | unsigned int N // size of state array
| unsigned int M // lag
| unsigned int a // "Magic numbers"
| unsigned int b,c //     "      "
| unsigned int u,s,t,l //     "      "
State:  | unsigned int state[N] // state vector
Output types:  | unsigned int (we return the current state).
| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.
| (See the implementation file for more details.)

Output range:  | Any number in the range [0,2^32] may be returned
Valid seeds:  | Using create:setStateFromSeed:  in [1,2^32-1]
| Using create:setStateFromSeeds: in [1,2^32-1].
Cycles:  | This generator has a single cycle of length 2^19937-1.
Output Quality:  | Excellent equidistribution properties in all dimensions
| up to 623 are claimed.
Reference for | Matsumoto and Nishimura, op. cit.
output quality:  | See also pLab Report #07 on the pLab web site.
MT19937gen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                           3.698 uS
|   -getFloatSample, getDoubleSample:           5.502 uS
|   -getFatDoubleSample, getLongDoubleSample: 10.159 uS
Relative speed:
| Speed 1.0 (time 1.0) relative to itself (it's the benchmark)
--------------- . -----------------------------------------------------------
--
Parameters:  | unsigned int w=32 // word length
| unsigned int N=624 // size of state array
| unsigned int M=397 // lag
| unsigned int s=7 // 'magic vector'
| unsigned int t=15 //     "      "
| unsigned int u=11 //     "      "
| unsigned int l=18 //     "      "
| unsigned int b=0x102d1200 //     "      "
| unsigned int c=0x66e50000 //     "      "
| unsigned int a=0x6b5eccf6 //     "      "
Reference for | Matsumoto and Nishimura, op. cit.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length 2^19937 -1,
| or 10^6001 !!! (The longest period yet.)
Output Quality:  | Good. Parameters chosen on the basis of theory
| and empirical testing.
Reference for | Matsumoto and Nishimura, op. cit.
output quality:  |

(./MRG5-7gen.html)
(./Interface.html)
(./MWCA-Bgen.html)
         Marcus G. Daniels <mgd@santafe.edu>
         (mailto:mgd@santafe.edu)
         Last modified:  1998-01-26

MWCA-Bgen Classes

//
// MWC --
//   two long generators recommended for use.
//
@deftype MWCAgen     <SingleLongGenerator, CREATABLE> @end
@deftype MWCBgen     <SingleLongGenerator, CREATABLE> @end

MWCAgen Documentation

Generator name:  | MWCA
Description:  | Multiply-With-Carry generator
Reference:  | Article posted to Usenet in 1994 by George Marsaglia,
| "The Mother of all Random Number Generators."
| Source found at <ftp://ftp.taygeta.com/pub/c/mother.c>
| Also document /papers/mwc1.ps on his Diehard CD-ROM,
| found at <http://www.hku.hk/internet/randomCD.html>.
Algorithm:  | K = a * (K & 65535) + (K>>16);
| J = b * (J & 65535) + (J>>16);
| return (K<<16) + J;
Comments:  | This generator is a combination of 2 16-bit
| Multiply-With-Carry generators.
Implementation:  |
Parameters:  | unsigned int a = 30903 // multiplier
| unsigned int b = 18000 // multiplier
State:  | unsigned int K,J // state vector
Output types:  | unsigned int (we return the current state).
| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.
| (See the implementation file for more details.)
Output range:  | Any number in the range [0,unsignedMax] = [0,2^32-1].

Valid seeds:  | Using create:setStateFromSeed:  [1, 2^32-1]
| Using create:setStateFromSeeds: each component may have
| a 'state' <= 65535 and a 'carry' <= (multiplier-1). Thus
| the first component has a maximum seed of
| ( (a-1) << 16) + 65535.
Cycles:  | This generator is claimed to be strictly periodic, with a
| period > 2^59. (There's possibly two such cycles.)
Output Quality:  | Good.
Reference for | Marsaglia, op. cit.
output quality:  |
MWCgen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                          3.399 uS
|   -getFloatSample, getDoubleSample:          5.131 uS
|   -getFatDoubleSample, getLongDoubleSample: 9.447 uS
Relative speed:
| Speed 1.088 (time 0.919) relative to MT19937 getUnsignedSample
--------------- . -----------------------------------------------------------
--

MWCBgen Documentation

Generator name:  | MWCB
Description:  | Multiply-With-Carry generator
Reference:  | Article posted to Usenet in 1994 by George Marsaglia,
| "The Mother of all Random Number Generators."
| Source found at <ftp://ftp.taygeta.com/pub/c/mother.c>
| Also document /papers/mwc1.ps on his Diehard CD-ROM,
| found at <http://www.hku.hk/internet/randomCD.html>.
Algorithm:  | K = a * (K & 65535) + (K>>16);
| J = b * (J & 65535) + (J>>16);
| return (K<<16) + (J&65535);
Comments:  | This generator is a combination of 2 16-bit
| Multiply-With-Carry generators.
Implementation:  | This generator implements an alternate manner of
| conjoining the two components (differs from MWCA).

| It also passes all tests and is fast.
Parameters:  | unsigned int a = 30903 // multiplier
| unsigned int b = 18000 // multiplier
State:  | unsigned int K,J // state vector
Output types:  | unsigned int (we return the current state).
| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.
| (See the implementation file for more details.)
Output range:  | Any number in the range [0,unsignedMax] = [0,2^32-1].
Valid seeds:  | Using create:setStateFromSeed:  [1, 2^32-1]
| Using create:setStateFromSeeds: each component may have
| a 'state' <= 65535 and a 'carry' <= (multiplier-1). Thus
| the first component has a maximum seed of
| ( (a-1) << 16) + 65535.
Cycles:  | This generator is claimed to be strictly periodic, with a
| period > 2^59. (There's possibly two such cycles.)
Output Quality:  | Good.
Reference for | Marsaglia, op. cit.
output quality:  |
MWCgen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                          3.399 uS
|   -getFloatSample, getDoubleSample:          5.131 uS
|   -getFatDoubleSample, getLongDoubleSample: 9.447 uS
Relative speed:
| Speed 1.088 (time 0.919) relative to MT19937 getUnsignedSample

(./MT19937gen.html)

(./Interface.html)
(./PMMLCG1-9gen.html)
Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-26

PMMLCG 1-9 Classes

//
// PMMLCG1, PMMLCG2, PMMLCG3 --
//   single short random number generators recommended for use.
//
// PMMLCG4, PMMLCG5, PMMLCG6, PMMLCG7 --
//   component generators of C4LCGX
//
// PMMLCG8, PMMLCG9 --
//   component generators of C2LCGX
//
@deftype PMMLCGgen   <SingleShortGenerator> @end
@deftype PMMLCG1gen  <PMMLCGgen, CREATABLE> @end
@deftype PMMLCG2gen  <PMMLCGgen, CREATABLE> @end
@deftype PMMLCG3gen  <PMMLCGgen, CREATABLE> @end
@deftype PMMLCG4gen  <PMMLCGgen, CREATABLE> @end
@deftype PMMLCG5gen  <PMMLCGgen, CREATABLE> @end
@deftype PMMLCG6gen  <PMMLCGgen, CREATABLE> @end
@deftype PMMLCG7gen  <PMMLCGgen, CREATABLE> @end
@deftype PMMLCG8gen  <PMMLCGgen, CREATABLE> @end
@deftype PMMLCG9gen  <PMMLCGgen, CREATABLE> @end

General Documentation

Generator name:  | PMMLCG
Description:  | Prime Modulus Multiplicative Linear Congruential Generator
Reference:  | Stephen K. Park and Keith W. Miller
| (CACM 31:10, October 1988, 1192-1201),
| "Random Number Generators: Good Ones Are Hard To Find."
| The authors refer to this generator as a "minimally
| acceptable" or "minimally sufficient" generator.
| state = seed
Algorithm:  | newstate = (a * oldstate) mod m
| output = state-1
Comments:  | The modulus m must be a prime for this class of generator
| (as opposed to the more common power of two modulus).
| For these generators we use m=2^31-1 (2,147,483,647).

| The choice of a good multiplier a is crucial.
Parameters:  | unsigned int m // modulus
| unsigned int a // multiplier
State:  | unsigned int state // a "state vector" of length 1
Output types:  | unsigned int (we return the current state-1).
| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.
| (See the implementation file for more details.)
Output range:  | The basic algorithm yields output in the range [1,m-1].
| We subtract 1 to return output in the range [0,m-2]
| (i.e. [0,2147483645].)
Valid seeds:  | create:setStateFromSeed:  [1, 2^32-1]
| create:setStateFromSeeds: [1, m-1]
Cycles:  | With properly chosen parameters, these generators
| have a single full cycle of length (m-1).
| (State=0 is an absorbing state which will not normally
| occur; we avoid setting the starting state to 0.)
Output Quality:  | All bits should be safe.
| (I.e. low order bits should not have small cycles.)
| With m prime, this generator is better than standard LCG.
Reference for | Park and Miller, op. cit.
output quality:  |
Implementation  | The code for -getUnsignedMax uses a trick devised by
comment:         | Schrage to avoid 32-bit overflow when calculating the
| next state (i.e. using q=m/a and r=m%a as auxiliary
| values). Using 64-bit math (long long integers) is more
| straightforward. Unfortunagely, on x86 at least, there
| is a 35% speed penalty for doing so. The output, however,
| is identical. YMMV.
PMMLCGgen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                           4.715 uS
|   -getFloatSample, getDoubleSample:           6.500 uS
|   -getFatDoubleSample, getLongDoubleSample: 12.152 uS

--------------- | -----------------------------------------------------------
---

PMMLCG1gen Documentation

Parameters:  | a =         16,807
| m = 2,147,483,647 (2^31-1)
Reference for | Park and Miller, op. cit.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length (m-1).
Output Quality:  | All bits should be safe.
| These parameters have been extensively tested by the authors.
Reference for | Park and Miller, op. cit.
output quality:  |

PMMLCG2gen Documentation

Parameters:  | a =         48,271
| m = 2,147,483,647 (2^31-1)
Reference for | Park and Miller, op. cit.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length (m-1).
Output Quality:  | All bits should be safe.
| These parameters are not as well tested as PMMLCG1,
| but there's reason to believe they may be better.
Reference for | Park and Miller, op. cit.
output quality:  |

PMMLCG3gen Documentation

Parameters:  | a =         69,621
| m = 2,147,483,647 (2^31-1)
Reference for | Park and Miller, op. cit.

choice of  |
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length (m-1).
Output Quality:  | All bits should be safe.
| These parameters are not as well tested as PMMLCG1,
| but there's reason to believe they may be better.
Reference for | Park and Miller, op. cit.
output quality:  |

PMMLCG4gen Documentation

Parameters:  | a =         45,991
| m = 2,147,483,647 (2^31-1)
Reference for | Pierre L'Ecuyer and Terry H. Andres,
choice of  | "A Random Number Generator Based on the Combination
parameters:  | of Four LCGs", unpubl.
| This is one of the component generators of their CLCG4.
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length (m-1).
Output Quality:  | All bits should be safe.
Reference for | L'Ecuyer and Andres, op.cit.
output quality:  |

PMMLCG5gen Documentation

Parameters:  | a =        207,707
| m = 2,147,483,543 (2^31-105)
Reference for | Pierre L'Ecuyer and Terry H. Andres,
choice of  | "A Random Number Generator Based on the Combination
parameters:  | of Four LCGs", unpubl.
| This is one of the component generators of their CLCG4.
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length (m-1).

Output Quality:  | All bits should be safe.
Reference for | L'Ecuyer and Andres, op.cit.
output quality:  |

PMMLCG6gen Documentation

Parameters:  | a =        138,556
| m = 2,147,483,423 (2^31-225)
Reference for | Pierre L'Ecuyer and Terry H. Andres,
choice of  | "A Random Number Generator Based on the Combination
parameters:  | of Four LCGs", unpubl.
| This is one of the component generators of their CLCG4.
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length (m-1).
Output Quality:  | All bits should be safe.
Reference for | L'Ecuyer and Andres, op.cit.
output quality:  |

PMMLCG7gen Documentation

Parameters:  | a =         49,689
| m = 2,147,483,323 (2^31-325)
Reference for | Pierre L'Ecuyer and Terry H. Andres,
choice of  | "A Random Number Generator Based on the Combination
parameters:  | of Four LCGs", unpubl.
| This is one of the component generators of their CLCG4.
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length (m-1).
Output Quality:  | All bits should be safe.
Reference for | L'Ecuyer and Andres, op.cit.
output quality:  |

PMMLCG8gen Documentation

Parameters:  | a =         40,014
| m = 2,147,483,563 (2^31-85)
Reference for | Pierre L'Ecuyer and Serge Cote,
choice of  | "Implementing a Random Number Package with Splitting
parameters:  | Facilities," ACM Trans. Math. Softw. 17 no 1 (March 1991).
| This is one of the component generators of their generator.
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length (m-1).
Output Quality:  | All bits should be safe.
Reference for | L'Ecuyer and Cote, op.cit.
output quality:  |

PMMLCG9gen Documentation

Parameters:  | a =         40,692
| m = 2,147,483,399 (2^31-249)
Reference for | Pierre L'Ecuyer and Serge Cote,
choice of  | "Implementing a Random Number Package with Splitting
parameters:  | Facilities," ACM Trans. Math. Softw. 17 no 1 (March 1991).
| This is one of the component generators of their generator.
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length (m-1).
Output Quality:  | All bits should be safe.
Reference for | L'Ecuyer and Cote, op.cit.
output quality:  |

(./MWCA-Bgen.html)

(./Interface.html)
(./PSWBgen.html)
Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-26

PSWBgen Class

//
// PSWB --
//   single long generator recommended for use.
//
@deftype PSWBgen   <SingleLongGenerator, CREATABLE> @end

Documentation

Generator name:  | PSWB
Description:  | Subtract-with-Borrow Congruential Generator
|     with Prime Modulus
Reference:  | George Marsaglia and Arif Zaman,
| "A New Class of Random Number Generators",
| Annals of Applied Probability vol 1 no 3 (1991), 462-480.
| SWB is an improvement on the Lagged Fibonacci generators.
| PSWB is an improvement on SWB in that the use of a prime
| modulus guarantees a single full cycle.
| It's slower, of course.
| state vector = f(seed)
Algorithm:  | state_n = (state_(n-s) - state_(n-r) - carry) mod m; r > s
| output = state_n
| These generators use a basic algorithm of the form
| X_n = f(X_(n-r),X_(n-s)) mod m; r>s
| The function f is typically xor, addition, subtraction,
| multiplication or subtraction with carry. It uses
| simpler math than a basic LCG, but keeps a larger state.
Implementation:  | The state vector contains the generator's r most recent
| outputs (X_n .. X_(n-r)). This vector is initialized from
| an LCG generator using one 32-bit seed value. After
| initialization we throw away r*5 numbers to 'prime' the
| generator (i.e. make sure we have entered a closed cycle.)
Parameters:  | unsigned int r // long lag
| unsigned int s // short lag

| unsigned int m // modulus
State:  | unsigned int state[r] // state vector
| int carry // carry bit
Output types:  | unsigned int (we return the current state).
| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.
| (See the implementation file for more details.)
Output range:  | Any number in the range [0,m-1] may be returned.
Valid seeds:  | Using create:setStateFromSeed:  [1,2^32-1]
| Using create:setStateFromSeeds: r seeds in [1,2^32-7]
| and one seed in [0,1] (the carry)
Cycles:  | With properly chosen parameters, this generator
| has a single cycle of length close to 10^414.
| Unfortunately, there are no 'jump-ahead' or 'splitting'
| facilities that would allow us to jump ahead in the cycle,
| other than calling the generator a number of times.
Output Quality:
| Much better than other Lagged Fibonacci generators, such as
| ACG and SCG.
Reference for | Marsaglia and Zaman, op.cit.
output quality:  |
PSWBgen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                          3.452 uS
|   -getFloatSample, getDoubleSample:          5.166 uS
|   -getFatDoubleSample, getLongDoubleSample: 9.544 uS
Relative speed:
| Speed 1.070 (time 0.933) relative to MT19937 getUnsignedSample
--------------- | -----------------------------------------------------------
---
Parameters:  | r = 43 // long lag
| s = 22 // short lag
| m = 2^32 - 5 // modulus (prime)
Reference for | Marsaglia, op. cit.
parameters:  |

Cycles:  | With the chosen parameters, this generator
| has a single cycle of length close to 10^414.
Output Quality:  | Good.
Reference for | Marsaglia, op.cit., p. 479
output quality:  |

(./PMMLCG1-9gen.html)

(./Interface.html)

(./RWC28gen.html)

Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-26

RWC2,8gen Classes

//
// RWC2 --
// RWC8 ("Mother") --
//   single long generator recommended for use.
//
@deftype RWC2gen   <SingleLongGenerator, CREATABLE> @end
@deftype RWC8gen   <CombinedLongGenerator, CREATABLE> @end

RWC2gen Documentation

Generator name:  | RWC2
Description:  | 2-lag Recursion-With-Carry generator
Reference:  | Article posted to Usenet in 1994 by George Marsaglia,
| "The Mother of all Random Number Generators."
| Source found at <ftp://ftp.taygeta.com/pub/c/mother.c>
| Also document /papers/rwc1.ps on his Diehard CD-ROM,
| found at <http://www.hku.hk/internet/randomCD.html>.
Algorithm:  | x[n]  = a*(x[n-1]+x[n-2]) + carry % 2^32
| carry = a*(x[n-1]+x[n-2]) + carry / 2^32
Comments:  | This generator is a 2-lag MWC generator
Implementation:  | This generator is implemented using 64-bit math
Parameters:  | unsigned int a = 1,111,111,464 // multiplier
State:  | unsigned int carry,x1,x2 // state vector
Output types:  | unsigned int (we return the current state).
| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.
| (See the implementation file for more details.)
Output range:  | Any number in the range [0,unsignedMax] = [0,2^32-1].
Valid seeds:  | Using create:setStateFromSeed:  [1, 2^32-1]

| Using create:setStateFromSeeds: x1 and x2: [1, 2^32-1]
| The carry can only be [1,a-1].
Cycles:  | This generator is claimed to have a period > 2^92.
| It may have rho sequences up to length r=2.
| It may have multiple cycles of the stated period length.
Output Quality:  | Good.
Reference for | Marsaglia, op. cit.
output quality:  |
RWC2gen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                           7.445 uS
|   -getFloatSample, getDoubleSample:           8.845 uS
|   -getFatDoubleSample, getLongDoubleSample: 17.338 uS
Relative speed:
| Speed 0.497 (time 2.013) relative to MT19937 getUnsignedSample

RWC8gen Documentation

Generator name:  | RWC8
Description:  | 8-lag Recursion-With-Carry generator
| ("The Mother of all RNG's")
Reference:  | Article posted to Usenet in 1994 by George Marsaglia,
| "The Mother of all Random Number Generators."
| Source found at <ftp://ftp.taygeta.com/pub/c/mother.c>
| Also document /papers/mwc1.ps on his Diehard CD-ROM,
| found at <http://www.hku.hk/internet/randomCD.html>.
Algorithm:  | x = sum(ai*xi) + carry mod 2^16
| y = sum(bi*yi) + carry mod 2^16
| return ((x<<16)+y)
Comments:  | This generator is a combination of 2 16-bit
| 8-lag Recursion-With-Carry generators.
Parameters:  | unsigned int a[8] =
| { 1941, 1860, 1812, 1776, 1492, 1215, 1066, 12013 }
| unsigned int b[8] =
| { 1111, 2222, 3333, 4444, 5555, 6666, 7777,  9272 }

State:  | unsigned short m1[10], m2[10] // state vector
Output types:  | unsigned int (we return the current state).
| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.
| (See the implementation file for more details.)
Output range:  | Any number in the range [0,unsignedMax] = [0,2^32-1].
Valid seeds:  | Using create:setStateFromSeed:  [1, 2^32-1]
| Using create:setStateFromSeeds:
|   a total of 18 16-bit seeds are needed;
|   each xi may be in [1, 2^31-1].
|   each carry may be in [1, sum(multipliers)-1].
Cycles:  | This generator is claimed to have a period > 2^250.
| It may have rho sequences up to length r = 8.
| It may have multiple cycles of the stated period length.
Output Quality:  | Claimed to be good.
Reference for | Marsaglia, op. cit.
output quality:  |
RWC8gen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                          14.649 uS
|   -getFloatSample, getDoubleSample:          16.400 uS
|   -getFatDoubleSample, getLongDoubleSample: 31.915 uS
Relative speed:
| Speed 0.252 (time 3.961) relative to MT19937 getUnsignedSample
--------------- . -----------------------------------------------------------
--

(./PSWBgen.html)

(./SCGgen.html)
Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-26

SCGgen Class

//
// SCG --
//   single long random number generator,
//   NOT recommended for serious use; included for
//   historical reasons (compatibility with earlier releases).
//
@deftype SCGgen      <SingleLongGenerator, CREATABLE> @end

Use of this generator is NOT Recommended

Documentation

Generator name:  | SCG
Description:  | Subtractive Congruential Generator
Reference:  | SCG is an often used algorithm, mentioned in Knuth,
| Numerical Recipes, etc.
| state vector = f(seed)
Algorithm:  | state_n = (state_(n-r) - state_(n-s)) mod 10^9; r > s
| output = state_n
| SCG is in the Lagged Fibonacci class of generators.
| These generators use a basic algorithm of the form
| X_n = f(X_(n-r),X_(n-s)) mod m; r>s
| The function f is typically xor, addition, subtraction,
| multiplication or subtraction with carry. It uses
| simpler math than a basic LCG, but keeps a larger state.
Implementation:  | The state vector contains the generator's r most recent
| outputs (X_n .. X_(n-r)). This vector is initialized from
| an LCG generator using one 32-bit seed value. After
| initialization we throw away r*5 numbers to 'prime' the
| generator (i.e. make sure we have entered a closed cycle.)
Parameters:  | unsigned int r // long lag

| unsigned int s // short lag
| unsigned int m // modulus
State:  | unsigned int state[r] // state vector
Output types:  | unsigned int (we return the current state).
| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.
| (See the implementation file for more details.)
Output range:  | Any number in the range [0,10^9-1] may be returned
| (i.e. [0,999999999].)
Valid seeds:  | Using create:setStateFromSeed:  [1,2^32-1]
| Using create:setStateFromSeeds: [1,999999998]
Cycles:  | With properly chosen parameters, these generators
| have a cycle of length about 2^r.
Output Quality:  | Low order bits are poor, and there are other problems.
| SWB is a better generator in the same class, and it is
| only slightly slower.
Reference for | Knuth, op.cit.
output quality:  |
SCGgen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                          3.328 uS
|   -getFloatSample, getDoubleSample:          5.058 uS
|   -getFatDoubleSample, getLongDoubleSample: 9.274 uS
Relative speed:
| Speed 1.111 (time 0.900) relative to MT19937 getUnsignedSample
--------------- | -----------------------------------------------------------
---
Parameters:  | r = 55
| s = 24
| m = 10^9
Reference for |
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length ~ 2^r.

          Output Quality:  | Low-order bits are poor.
          Reference for | Knuth, op.cit.
          output quality:  |

(./RWC28gen.html)

(./Interface.html)

(./SWB1-3gen.html)

         Marcus G. Daniels <mgd@santafe.edu>
         (mailto:mgd@santafe.edu)
         Last modified:  1998-01-26

SWB1-3gen Classes

//
// SWB1, SWB2, SWB3 --
//   single long generators recommended for use.
//
@deftype SWBgen   <SingleLongGenerator> @end
@deftype SWB1gen     <SWBgen, CREATABLE> @end
@deftype SWB2gen     <SWBgen, CREATABLE> @end
@deftype SWB3gen     <SWBgen, CREATABLE> @end

General Documentation

Generator name:  | SWB
Description:  | Subtract-with-Borrow Congruential Generator
Reference:  | George Marsaglia and Arif Zaman,
| "A New Class of Random Number Generators",
| Annals of Applied Probability vol 1 no 3 (1991), 462-480.
| SWB is an improvement on the Lagged Fibonacci generators.
| state vector = f(seed)
Algorithm:  | state_n = (state_(n-s) - state_(n-r) - carry) mod 2^32; r > s
| output = state_n
| These generators use a basic algorithm of the form
| X_n = f(X_(n-r),X_(n-s)) mod m; r>s
| The function f is typically xor, addition, subtraction,
| multiplication or subtraction with carry. It uses
| simpler math than a basic LCG, but keeps a larger state.
Note:  | This generator relies on controlled overflow at 32 bits.
| This requires that unsigned be a 32bit value that follows
| ANSI C rules.
Implementation:  | The state vector contains the generator's r most recent
| outputs (X_n .. X_(n-r)). This vector is initialized from
| an LCG generator using one 32-bit seed value. After
| initialization we throw away r*5 numbers to 'prime' the
| generator (i.e. make sure we have entered a closed cycle.)

State:  | unsigned int state[r] // state vector
| int carry // carry bit
Output types:  | unsigned int (we return the current state).
| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.
| (See the implementation file for more details.)
Output range:  | Any number in the range [0,2^32-1] may be returned
| (i.e. [0,4294967295].)
Valid seeds:  | Using create:setStateFromSeed:  [1,2^32-1]
| Using create:setStateFromSeeds: r seeds in [1,2^32-2]
| and one seed in [0,1] (the carry)
Cycles:  | With properly chosen parameters, these generators
| have a number of long cycles, up to 10^354 in length.
| UNFORTUNATELY there is no way to pick different
| cycles, nor any easy way to 'jump ahead' in the
| chosen cycle (other than calling -getUnsignedSample
| a number of times).
Output Quality:
| Much better than other Lagged Fibonacci generators, such as
| ACG and SCG.
Reference for | Marsaglia and Zaman, op.cit.
output quality:  |
SWBgen | On a 486/66, the following approximate measures were obtained:
speed:  |   -getUnsignedSample:                          3.285 uS
|   -getFloatSample, getDoubleSample:          5.057 uS
|   -getFatDoubleSample, getLongDoubleSample: 9.209 uS
Relative speed:
| Speed 1.126 (time 0.888) relative to MT19937 getUnsignedSample
--------------- | -----------------------------------------------------------
---

SWB1gen Documentation

Parameters:  | r = 37

| s = 24
Reference for | Marsaglia, op. cit.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has 64 cycles of length 10^354
Output Quality:  | Good.
Reference for | Marsaglia, op.cit., p. 479
output quality:  |

SWB2gen Documentation

Parameters:  | r = 24
| s = 19
Reference for | Marsaglia, op. cit.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has 1536 cycles of length 10^228
Output Quality:  | Good.
Reference for | Marsaglia, op.cit., p. 479
output quality:  |

SWB3gen Documentation

Parameters:  | r = 21
| s =  6
Reference for | Marsaglia, op. cit.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has 192 cycles of length 10^200
Output Quality:  | Good.
Reference for | Marsaglia, op.cit., p. 479
output quality:  |

(./SCGgen.html)
(./Interface.html)
(./TGFSRgen.html)
         Marcus G. Daniels <mgd@santafe.edu>
         (mailto:mgd@santafe.edu)
         Last modified:  1998-01-26

TGFSRgen Classes

//
// TT403, TT775, TT800 --
//   single long generators recommended for use.
//
@deftype TGFSRgen     <SingleLongGenerator>  @end
@deftype TT403gen      <TGFSRgen, CREATABLE> @end
@deftype TT775gen      <TGFSRgen, CREATABLE> @end
@deftype TT800gen      <TGFSRgen, CREATABLE> @end

General Documentation

Generator name:  | TGFSR
Description:  | Twisted GFSR generator
Reference:  | Makoto Matsumoto and Yoshiharu Kurita,
| "Twisted GFSR Generators II".
| ACM TOMACS, vol 4 no 3 July 1994 pp. 254-266.
| Amended by M. Matsumoto, July 8 1996.
|
Algorithm:  |
|
Comments:  |
Implementation:  |
Parameters:  | unsigned int w // word length
| unsigned int N // size of state array
| unsigned int M // lag
| unsigned int s // 'magic vector'
| unsigned int t //     "      "
| unsigned int b //     "      "
| unsigned int c //     "      "
| unsigned int a //     "      "
State:  | unsigned int state[N] // state vector
Output types:  | unsigned int (we return the current state).

| float in [0.0,1.0) using 1 iteration of the generator.
| double in [0.0,1.0) using 1 or 2 iterations of the generator.
| long double in [0.0,1.0) using 2 iterations of the generator.
| (See the implementation file for more details.)
Output range:  | Any number in the range [0,2^w-1] may be returned
Valid seeds:  | Using create:setStateFromSeed:  in [1,2^32-1]
| Using create:setStateFromSeeds: in [1,2^w-1].
Cycles:  | With properly chosen parameters, these generators
| have a single cycle of length 2^(w*N) -1.
Output Quality:  | Good.
Reference for | Matsumoto and Kurita, op. cit.
output quality:  | Also recommended by P. L'Ecuyer (private communication).
TT403gen, | On a 486/66, the following approximate measures were obtained:
TT775gen, |   -getUnsignedSample:                           4.654 uS
TT800gen |   -getFloatSample, getDoubleSample:           6.430 uS
speed:  |   -getFatDoubleSample, getLongDoubleSample: 11.953 uS
Relative speed:
| Speed 0.795 (time 1.259) relative to MT19937 getUnsignedSample
--------------- . -----------------------------------------------------------
--

TT403gen Documentation

Parameters:  | unsigned int w=31 // word length
| unsigned int N=13 // size of state array
| unsigned int M=2 // lag
| unsigned int s=8 // 'magic vector'
| unsigned int t=14 //     "      "
| unsigned int b=0x102d1200 //     "      "
| unsigned int c=0x66e50000 //     "      "
| unsigned int a=0x6b5eccf6 //     "      "
Reference for | Matsumoto and Kurita, op. cit.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length 2^403 -1.
Output Quality:  | Good. Parameters chosen on the basis of theory

| and empirical testing.
Reference for | Matsumoto and Kurita, op. cit.
output quality:  |

TT775gen Documentation

Parameters:  | unsigned int w=31 // word length
| unsigned int N=25 // size of state array
| unsigned int M=8 // lag
| unsigned int s=6 // 'magic vector'
| unsigned int t=14 //     "      "
| unsigned int b=0x1abd5900 //     "      "
| unsigned int c=0x776a0000 //     "      "
| unsigned int a=0x6c6cb38c //     "      "
Reference for | Matsumoto and Kurita, op. cit.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length 2^775 -1.
Output Quality:  | Good. Parameters chosen on the basis of theory
| and empirical testing.
Reference for | Matsumoto and Kurita, op. cit.
output quality:  |

TT800gen Documentation

Parameters:  | unsigned int w=32 // word length
| unsigned int N=25 // size of state array
| unsigned int M=7 // lag
| unsigned int s=7 // 'magic vector'
| unsigned int t=15 //     "      "
| unsigned int b=0x2b5b2500 //     "      "
| unsigned int c=0xdb8b0000 //     "      "
| unsigned int a=0x8ebfd028 //     "      "
Reference for | Matsumoto and Kurita, op. cit.
parameters:  |
Cycles:  | With the chosen parameters, this generator
| has a single full cycle of length 2^800 -1.

          Reference for | Matsumoto and Kurita, op. cit.
          output quality:  |

(./SWB1-3gen.html)

(./Interface.html)

(./Prot.html#ProbabilityDist)

         Marcus G. Daniels <mgd@santafe.edu>
         (mailto:mgd@santafe.edu)
         Last modified:  1998-01-26

RandomBitDistribution Class

//
// RandomBitDistribution --
//   A generator that returns uniformly distributed single bit values
//   (i.e. fair coin tosses).
//
@deftype RandomBitDist <BooleanDistribution, CREATABLE>
USING
- (BOOL) getCoinToss;
@end

Documentation

Name:  | RandomBitDistribution
Description:  | Distribution returning YES and NO with equal probability
Algorithm:  | Extract a middle bit from an unsigned random number
Reference:  | (none)
Parameters:  | (none)
State:  | unsigned long long int currentCount
RandomBitDist | On a 486/66, the following measures were obtained,
speed:  | using MT19937 as the underlying generator:
|  -getBooleanSample:                             5.656 uS
|  -average # of generator calls per variate: 1.000 (U)
|  -distribution net time:                       1.958 uS
Relative speed:
| Speed 0.654 (time 1.529) relative to MT19937 getUnsignedSample
--------------- . -----------------------------------------------------------
--

(Interface.html)
(BernoulliDist.html)
Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-10

BernoulliDistribution Class

//
// BernoulliDistribution --
distribution returning YES with given probability p
//
@deftype BernoulliDist <BooleanDistribution, CREATABLE>
CREATING
+ create: aZone setGenerator: generator
                  setProbability: (double) p;
+ create: aZone setGenerator: generator
setVirtualGenerator: (unsigned) vGen
                  setProbability: (double) p;
USING
- setProbability: (double) p;
- (double) getProbability;
- (BOOL)         getSampleWithProbability: (double) p;
@end

Documentation

Name:  | BernoulliDistribution
Description:  | Distribution returning binary value YES with probability p
Algorithm:  | Rejection method
Reference:  | Code contributed by Barry McMullin
Parameters:  | double Probability
State:  | unsigned long long int currentCount
BernoulliDist | On a 486/66, the following measures were obtained,
speed:  | using MT19937 as the underlying generator:
|  -getBooleanSample:                             8.156 uS
|  -average # of generator calls per variate: 1.000 (tD)
|  -distribution net time:                       2.654 uS

          --------------- . -----------------------------------------------------------
          --

(./RandomBitDist.html)

(./Interface.html)

(./UniformIntegerDist.html)

         Marcus G. Daniels <mgd@santafe.edu>
         (mailto:mgd@santafe.edu)
         Last modified:  1998-01-26

UniformIntegerDist Class

//
// UniformInteger --
//   A generator of integral values uniformly distributed across a closed
//   interval [min,max]. (The interval includes both its endpoints.)
//   Setting minValue == maxValue is allowed (and returns minValue).
//
@deftype UniformIntegerDist <IntegerDistribution, CREATABLE>
CREATING
+ create: aZone setGenerator: generator
                  setIntegerMin: (int) minValue setMax: (int) maxValue;
+ create: aZone setGenerator: generator
setVirtualGenerator: (unsigned) vGen
                  setIntegerMin: (int) minValue setMax: (int) maxValue;
USING
- setIntegerMin: (int) minValue setMax: (int) maxValue;
- (int) getIntegerMin;
- (int) getIntegerMax;
- (int) getIntegerWithMin: (int) minValue withMax: (int) maxValue;
@end

Documentation

Name:  | UniformInteger
Description:  | Distribution returning integers over an interval [min,max]
Algorithm:  | Transformation of uniform unsigneds [0,unsignedMax]
Reference:  | (none)
Parameters:  | integer minValue
| integer maxValue
State:  | unsigned long long int currentCount
Implementation  | Setting minValue=maxValue is allowed.
comment:         | Then minValue is retured "with probability 1".
UniformIntegerDist | On a 486/66, the following measures were obtained,
speed:  | using MT19937 as the underlying generator:

|  -getIntegerSample:                             7.534 uS
|  -average # of generator calls per variate: 1.000 (U)
|  -distribution net time:                       3.836 uS
Relative speed:
| Speed 0.491 (time 2.037) relative to MT19937 getUnsignedSample
--------------- . -----------------------------------------------------------
--

(./BernoulliDist.html)

(./Interface.html)

(./UniformUnsignedDist.html)

Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-26

UniformUnsignedDist Class

//
// UniformUnsigned --
//   A generator of non-negative integral values uniformly distributed across
//   a closed interval [min,max].  (The interval in-
cludes both its endpoints.)
//   Setting minValue == maxValue is allowed (and returns minValue).
//
@deftype UniformUnsignedDist <UnsignedDistribution, CREATABLE>
CREATING
+ create: aZone setGenerator: generator
                  setUnsignedMin: (unsigned) minValue setMax: (un-
signed) maxValue;
+ create: aZone setGenerator: generator
setVirtualGenerator: (unsigned) vGen
                  setUnsignedMin: (unsigned) minValue setMax: (un-
signed) maxValue;
USING
- setUnsignedMin: (unsigned) minValue setMax: (unsigned) maxValue;
- (unsigned) getUnsignedMin;
- (unsigned) getUnsignedMax;
- (unsigned) getUnsignedWithMin: (unsigned) minVal
             withMax: (unsigned) maxVal;
@end

Documentation

Name:  | UniformUnsigned
Description:  | Distribution returning unsigneds over an interval [min,max]
Algorithm:  | Transformation of uniform unsigned [0,unsignedMax]
Reference:  | (none)
Parameters:  | unsigned minValue
| unsigned maxValue
State:  | unsigned long long int currentCount
Implementation  | Setting minValue=maxValue is allowed.

comment:         | Then minValue is returned "with probability 1".
UniformUnsignedDist | On a 486/66, the following measures were obtained,
speed:  | using MT19937 as the underlying generator:
|  -getUnsignedSample:                           7.632 uS
|  -average # of generator calls per variate: 1.000 (U)
|  -distribution net time:                       3.934 uS
Relative speed:
| Speed 0.485 (time 2.064) relative to MT19937 getUnsignedSample
--------------- . -----------------------------------------------------------
--

(./UniformIntegerDist.html)

(./Interface.html)

(./UniformDoubleDist.html)

Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-26

UniformDoubleDist Class

//
// UniformDouble --
//   A generator of floating point values uniformly distributed
//   across a half-open interval [min,max). (The interval includes
//   the lower endpoint but excludes the upper endpoint.)
//   NOTE: Setting minValue == maxValue is allowed (and returns minValue).
//
@deftype UniformDoubleDist <DoubleDistribution, CREATABLE>
CREATING
+ create: aZone setGenerator: generator
                  setDoubleMin: (double) minValue setMax: (double) maxValue;
+ create: aZone setGenerator: generator
setVirtualGenerator: (unsigned) vGen
                  setDoubleMin: (double) minValue setMax: (double) maxValue;
USING
- setDoubleMin: (double) minValue setMax: (double) maxValue;
- (double) getDoubleMin;
- (double) getDoubleMax;
- (double) getDoubleWithMin: (double) minValue withMax: (double) maxValue;
@end

Documentation

Name:  | UniformDouble
Description:  | Distribution returning doubles over an interval [min,max)
Algorithm:  | Transformation of uniform double [0.0,1.0)
Reference:  | (none)
Parameters:  | double minValue
| double maxValue
State:  | unsigned long long int currentCount
Implementation | Setting minValue=maxValue is allowed.
comment:  | Then minValue is returned "with probability 1".
UniformDoubleDist | On a 486/66, the following measures were obtained,

speed:  | using MT19937 as the underlying generator:
|  -getDoubleSample:                              13.777 uS
|  -average # of generator calls per variate:  1.000 (D)
|  -distribution net time:                        3.618 uS
Relative speed:
| Speed 0.268 (time 3.726) relative to MT19937 getUnsignedSample
--------------- . -----------------------------------------------------------
--

(./UniformUnsignedDist.html)

(./Interface.html)

(./ExponentialDist.html)

Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-26

ExponentialDistribution Class

//
// ExponentialDistribution -- a well-
known continuous probability distribution
//
@deftype ExponentialDist <DoubleDistribution, CREATABLE>
CREATING
+ create: aZone setGenerator: generator
                  setMean: (double) mean;
+ create: aZone setGenerator: generator
setVirtualGenerator: (unsigned) vGen
                  setMean: (double) mean;
USING
- setMean: (double) mean;
- (double) getMean;
- (double) getSampleWithMean: (double) mean ;
@end

Documentation

Name:  | ExponentialDistribution
Description:  | Exponential distribution returning double values
Algorithm:  | Transformation method
Reference:  | Russell 1992
Parameters:  | double Mean
State:  | unsigned long long int currentCount
ExponentialDist | On a 486/66, the following measures were obtained,
speed:  | using MT19937 as the underlying generator:
|  -getDoubleSample:                              20.905 uS
|  -average # of generator calls per variate:  1.000 (D)
|  -distribution net time:                       10.746 uS

(./UniformDoubleDist.html)

(./Interface.html)

(./GammaDist.html)

         Marcus G. Daniels <mgd@santafe.edu>
         (mailto:mgd@santafe.edu)
         Last modified:  1998-01-26

GammaDistribution Class

//
// GammaDistribution -- a well-known continuous probability distribution
//
@deftype GammaDist <DoubleDistribution, CREATABLE>
CREATING
+ create: aZone setGenerator: generator
setAlpha: (double) alpha setBeta: (double) beta;
+ create: aZone setGenerator: generator
setVirtualGenerator: (unsigned) vGen
setAlpha: (double) alpha setBeta: (double) beta;
USING
- setAlpha: (double) alpha setBeta: (double) beta;
- (double) getAlpha;
- (double) getBeta;
- (double) getSampleWithAlpha: (double) alpha
withBeta: (double) beta;
@end

Documentation

Name:  | GammaDistribution
Description:  | Gamma distribution returning double values
Algorithm:  | Transformation, rejection and xxx methods.
Reference:  | Watkins 1994.
Parameters:  | double Alpha
| double Beta
State:  | unsigned long long int currentCount
GammaDist | On a 486/66, the following measures were obtained,
speed:  | using MT19937 as the underlying generator:
|  -getDoubleSample:                              119.424 uS
|  -average # of generator calls per variate:   6.224 (D)
|  -distribution net time:                        56.194 uS

Relative speed:
| 0.00310 (time 32.294) relative to MT19937 getUnsignedSample
--------------- . -----------------------------------------------------------
--

(./ExponentialDist.html)

(./Interface.html)

(./NormalDist.html)

Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-10

Normal and LogNormalDistribution Classes

//
// NormalDistribution -- a well-known continuous probability distribution
// LogNormalDistribution -- also well-known ...
//
@deftype NormalDist     <Normal, CREATABLE> @end
@deftype LogNormalDist <Normal, CREATABLE> @end

NormalDist Documentation

Name:  | NormalDistribution
Description:  | Normal (Gaussian) distribution returning double values
Algorithm:  | The Box-Muller method
Reference:  | W.H. Press et al, "Numerical Recipes in C" (2nd ed.).
| Cambridge University Press, 1992.
Parameters:  | double Mean
| double Variance
State:  | double stored_value
| BOOL stored
| unsigned long long int currentCount
NormalDist | On a 486/66, the following measures were obtained,
speed:  | using MT19937 as the underlying generator:
|  -getDoubleSample:                              24.729 uS
|  -average # of generator calls per variate:  1.273 (D)
|  -distribution net time:                       11.797 uS
Relative speed:
| Speed 0.150 (time 6.687) relative to MT19937 getUnsignedSample
--------------- . -----------------------------------------------------------
--

LogNormalDist Documentation

Name:  | LogNormalDistribution
Description:  | Log-Normal distribution returning double values
Reference:  | W.H. Press et al, "Numerical Recipes in C" (2nd. ed.).
| Cambridge University Press, 1992.
Algorithm:  | The Box-Muller method
Parameters:  | double Mean
| double Variance
State:  | double stored_value
| BOOL stored
| unsigned long long int currentCount
Output types:  | double
Output Quality:  | All bits should be safe.
LogNormalDist | On a 486/66, the following measures were obtained,
speed:  | using MT19937 as the underlying generator:
|  -getDoubleSample:                              33.430 uS
|  -average # of generator calls per variate:  1.273 (D)
|  -distribution net time:                       20.498 uS
Relative speed:
| Speed 0.111 (time 9.040) relative to MT19937 getUnsignedSample
--------------- . -----------------------------------------------------------
--

(GammaDist.html)
(Interface.html)

(RandomBitDist.html)
Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-10

Random Library: Usage Guide

Table Of Contents:

1.Overview
2.Generator Usage
3.Distribution Usage

Overview

The random library basically consists of two parts, the actual pseudorandom number
algorithms and the transformations that change the output of the pseudorandom number
algorithms into the simulated distributions.  The pseudorandom number algorithms are
called generators throughout these documents and many times the "pseudo" is dropped
from pseudorandom, even though there is no true random number generator implemented
in Swarm.

Generator Usage Notes

Primary Author:  Sven Thommesen
(mailto:sthomme@humsci.auburn.edu)
Swarm rel.  1.0.3 (random rel.  0.8)
Notes on the use of the random number generators
Sven Thommesen <sthomme@humsci.auburn.edu>
1997-09-01
IMPROVEMENTS over v. 0.6:
A host of new generators, located on the web or in the literature, have
been added since the last version of Random. There is now a total of 36
different generators defined! Some of these have immense periods, some
are very fast, and some have much better statistical properties than
the old generators.
A new *type* of generator, the 'split' generator, has been introduced
in the form of L'Ecuyer's C2LCGXgen and C4LCGXgen generators.
A 'split' generator is a long-period generator for which we are able to
split the period into arbitrary sub-periods, which we can access quickly.

We then configure the generator as having a number (A) of 'vir-
tual generators',
each of which can address a number (2^v) of sub-segments of length 2^w.
These parameters (A,v,w) are user selectable when the generator is created.
(As an example, for C4LCGXgen the default values are A=128, v=31, w=41.)
The advantage is that the subsegments act as statistically independent
streams of random numbers.
In addition to the -getUnsignedSample method, generators now also supply
floating point output in the range [0.0,1.0), in the form of these methods:
   -(float)        getFloatSample; // using 1 unsigned value
   -(double)       getThinDoubleSample; // using 1 unsigned value
   -(double)       getDoubleSample; // using 2 unsigned values
   -(long double) getLongDoubleSample; // using 2 unsigned values
The last method is not portable across architectures, since the length of a
long double varies between machines.
Generators may now be started with a single seed, *or* with a vector of seeds
whose length is generator dependent. (PMMLCG requires 1 integer for a
seed, while MT19937 needs 624 of them.)
Generators now remember what seed values they were started with. They also
count how many variates they have delivered (i.e., how many calls to
-getUnsignedSample they have serviced.)
There are a few arbitrary seed values, DEFAULTSEED, DEFAULT-
SEED1, DEFAULTSEED2,
DEFAULTSEED3, DEFAULTSEED4 defined. There is the value RANDOMSEED, which will
be different every time it is invoked. And there is value START-
SEED, which will
by default equal DEFAULTSEED, but will instead be equal to RANDOMSEED if you
start your program with the '-varySeed' command line parameter.
The generators have gained a new creation method, '+createWithDe-
faults: aZone',
which creates the generator and initializes it with STARTSEED. Split
generators get default values for A,v,w.

CHANGES since v. 0.6:
The generator classes have changed names to where they all end in '-gen'.
A simple search-and-replace in your code will get you up and running again.
(Or perhaps you'll want to try one of the new generators?)

A bug in SWBgen was corrected. Code for ACG and SCG was also changed.
The -verifySelf method is gone. Instead see the test program located in
/random/testR0.
The 'getState:' method has been named 'putStateInto: (void *) buffer',
and the 'setState:' method is now 'setStateFrom: (void *) buffer'.
A quick search-and-replace fixes things in your code.
Note: these methods have also changed somewhat, as has the size of the
data being saved. As a result, v. 0.7 generators will refuse to
'setStateFrom' data saved by v. 0.6 objects.
There should be fewer changes like this in the next release.
USAGE notes:
------------
I shall first discuss 'simple' generators, and then discuss how 'split'
generators differ from 'simple' ones.
In the following text, wherever I use PSWBgen as an example you may
substitute any other generator.
Note: any name that starts with 'my' is meant to designate a variable
which you have defined in your own program.
SIMPLE generators:
------------------
You create a generator in one of 3 ways:
(a) the lazy way:
   myGenerator = [ PSWBgen createWithDefaults: [self getZone] ];
This allocates the object and initializes it with STARTSEED.
(b) using a single seed value:
   myGenerator = [ PSWBgen create: [self getZone]
setStateFromSeed: mySeed ];

This allocates the object and initializes it with your seed value. If the
object actually requires a vector of seed values to fill the state, this
method generates the rest of the values needed using an inline PMMLCG
generator.
You can find out later what seed value was used to initialize the generator:
   myUnsigned = [ myGenerator getInitialSeed ];
And you can find out what the largest valid seed value is by calling
   myUnsigned = [ myGenerator getMaxSeedValue ];
(For the generators defined in v. 0.7, this value is 2^32-1 for all of them.
The seed may not be 0.)
You may reset the generator's state at any time using this method:
   [ myGenerator setStateFromSeed: mySeedValue ];
(c) using a vector of seed values:
Assume we have defined a fixed array at compile time:
   unsigned int mySeedVector [vectorLength];
Then we can do this:
   myGenerator = [ PSWBgen create: [self getZone]
setStateFromSeeds: mySeedVector ];
You can find out how many seed values are required by asking
   myUnsigned = [ myGenerator lengthOfSeedVector ];
(Obviously, you must first successfully have created the object to do this,
for example using createWithDefaults!)
And we allocate the seed vector dynamically this way:
   unsigned int *mySeedVector;
   mySeedVector = [[self getZone] alloc: [ myGenerator lengthOfSeedVector]];
You can find out what vector of seed values was used to initial-
ize the object:
   unsigned int *myVector;

   myVector = [ myGenerator getInitialSeeds ];
And you can find out the largest seed values that are allowed for the
particular generator:
   myVector = [ myGenerator getMaxSeedValues ];
(These values vary from generator to generator, and they may not be the same
for all elements of the vector for a given generator. Seeds may not be 0.)
NOTE: in the above two calls, the variable myVector is set to point to an
array internal to the generator. If you want to preserve the values, you
need to allocate space in your program either statically or dynamically,
and use a for-loop to copy data from myVector[i] to myAllocatedVector[i].
You may reset the generator's state at any time by using the method
   [ myGenerator setStateFromSeeds: (unsigned *) mySeedVector ];
This will also reset to 0 the currentCount variable.
NOTE: if you set a generator's state from a vector of seeds, the call
   myUnsignedValue = [ myGenerator getInitialSeed ];
will return a value of 0 (an invalid seed). On the other hand, if you
initialize the generator with a single seed value, the call
   mySeedVector = [ myGenerator getInitialSeeds ];
will return the seed vector that would produce identical output to what
you obtained using the single seed.
(d) antithetic values:
You can make the generator serve up antithetic values by setting:
   [ myGenerator setAntithetic: myBooleanValue ];
If set, this makes -getUnsignedSample return (unsignedMax-x) instead of x,
and the floating point methods return (1.0 - y) instead of y.
You can ascertain if this flag is set by calling
   myBooleanValue = [ myGenerator getAntithetic ];

(e) generator output:
You obtain successive pseudorandom numbers from a generator by calling
   myUnsignedValue = [ myGenerator getUnsignedSample ];
The largest value thus returned can be found by asking
   myUnsignedValue = [ myGenerator getUnsignedMax ];
(The smallest value returned is always 0.)
If you would rather have floating point output in the range [0.0,1.0),
you call one of these:
// Using 1 unsigned value to fill the mantissa:
   myFloatValue  = [ myGenerator getFloatSample ];
   myDoubleValue = [ myGenerator getThinDoubleSample ];
// Using 2 unsigned values to fill the mantissa:
   myDoubleValue      = [ myGenerator getDoubleSample ];
   myLongDoubleValue = [ myGenerator getLongDoubleSample ];
NOTE that the last method is not portable, because the size of a long double
varies and hence the precision varies between architectures.
Finally, you can obtain a count of how many variates have been generated:
   myLongLongInt = [ myGenerator getCurrentCount ];
(currentCount is an unsigned long long int, which counts up to 2^64.)
SPLIT generators:
-----------------
A 'split' generator requires us to specify the configuration (A,v,w)
at create time:
   myGenerator = [ C4LCGXgen create: [self getZone]
setA: 64 setv: 20 setw: 76
setStateFromSeed: mySeedValue ];

myGenerator = [ C4LCGXgen create: [self getZone]
setA: 32 setv: 25 setw: 60
setStateFromSeeds: (unsigned *) mySeedVector ];
(In both cases, the only limitation is that A * 2^v * 2^w must be less than
the generator's period, 2^60 for C2LCGX and 2^120 for C4LCGX.)
For obtaining output, we need to specify which of the A 'virtual' generators
we want to draw from:
myUnsignedValue = [ myGenerator getUnsignedSample: 12 ];
myFloatValue     = [ myGenerator getFloatSample: myVirtualGenerator ];
myDoubleValue   = [ myGenerator getThinDoubleSample: someUnsignedValue ];
myDoubleValue   = [ myGenerator getDoubleSample: 32 ];
myLongDoubleValue = [ myGenerator getLongDoubleSample: 0 ];
Note: virtual generators are numbered from 0 to A-1.
Obtaining the current count of variates generated likewise:
myLongLongInt = [ myGenerator getCurrentCount: myVirtualGenerator ];
myLongLongInt = [ myGenerator getCurrentSegment: myVirtualGenerator ];
The latter call indicates what segment number the virtual generator is
currently drawing numbers from.
Other than these methods, the other methods discussed above under 'simple'
generators are the same for 'split' generators.
In *addition* to this, 'split' generators have the following methods to
manage the virtual generators:
// Place all virtual generators at the start of the first segment:
[ myGenerator initAll ]; // done automatically at creation
// Place all virtual generators back to the start of the current segment:
[ myGenerator restartAll ];
// Place all virtual generators at the start of the next segment:
[ myGenerator advanceAll ];
// Place all virtual generators at the start of the indicated segment:
[ myGenerator jumpAllToSegment: myLongLongIntValue ];
You may also address individual virtual generators:
[ myGenerator initGenerator:     myVgen ];

[ myGenerator restartGenerator: myVgen ];
[ myGenerator advanceGenerator: myVgen ];
[ myGenerator jumpGenerator:     myVgen     toSegment: myLongLongIntValue ];

InternalState methods common to simple and split generators:

// Print (most of) the object's state data to a stream:
[ myNormalDist describe: myStream ];
The stream myStream may be created thus:
id myStream = [ OutStream create: [self getZone] setFileStream: stdout ]; or
id myStream = [ OutStream create: [self getZone] setFileStream: stderr ];
// Get the (class) name of the object:
myString = [ myNormalDist getName ];
// Get the object's 'magic number', used by putStateInto / setStateFrom:
myUnsigned = [ myNormalDist getMagic ];

SAVING AND RESETTING STATE:
You may save, and later restore, the internal state of a generator
using these methods:
// Get the size of the memory buffer needed by put-
StateInto / setStateFrom:
myUnsigned = [ myGenerator getStateSize ];
// Extract the generator's state data into your memory buffer:
[ myGenerator putStateInto: myBuffer ];
// Set the generator's state from data in a memory buffer:
[ myGenerator setStateFrom: myBuffer ];

To illustrate, assume the following data definitions:
FILE *myFile;
const char *myFileName = "MyGenFile.bin"; // or whatever
int stateSizeG;
id stateBufG;
int status;

The following code shows how to save an object's state to disk:
(You should add your own code to deal with disk file errors,
either aborting or printing out error messages.)
// Ask how big a buffer we need:
stateSizeG = [ myGenerator getStateSize ];
// Allocate memory for the buffer:
stateBufG  = [[self getZone] alloc: stateSizeG];
// Ask the generator to put state data into the buffer:
[ myGenerator putStateInto: (void *) stateBufG ];
// Open a disk file for output:
myFile = fopen(myFileName, "w");
if (myFile == NULL) { }; // error on open: disk full, or no permissions
// Write the state buffer to disk in binary form:
status = fwrite(stateBufG, stateSizeG, 1, myFile);
if (status < 1) { }; // error on write: disk full?
// Close the file
status = fclose(myFile);
if (status) { }; // error on close ?
// Free the memory allocated to the buffer:
[[self getZone] free: stateBufG];
// Or, for test purposes, just zero the buffer data instead:
// memset(stateBufG, 0, stateSizeG);

This code shows how to set an object's state from a disk file:
// Ask how big a buffer we need:
stateSizeG = [ myGenerator getStateSize ];
// Allocate memory for the buffer:
stateBufG  = [[self getZone] alloc: stateSizeG];
// Open a disk file for input:
myFile = fopen(myFileName, "r");
if (myFile == NULL) { }; // error on open: file not found
// Read state data into the memory buffer:
status = fread(stateBufG, stateSizeG, 1, myFile);
if (status < 1) { }; // error on read

   // Close the file:
   status = fclose(myFile);
   if (status) { }; // error on close
   // Ask the generator set its state from the buffer data:
   [ myGenerator setStateFrom: (void *) stateBufG ];
   // Free the memory allocated to the buffer:
   [[self getZone] free: stateBufG];

TESTING GENERATORS:
Since v. 0.6 we have done some rudimentary statistical testing of the
implemented generators, using Marsaglia's Diehard tests and the ENT tests.
The results of these tests are summarized in document
/random/docs/doc.quality.generators, where test results as well as period
length, state size and execution times are listed. You can use these data to
select a generator that suits your simulation.
Some brief comments:
a) the tests show that old generators SCG and LCG are of poor quality and
should be avoided.
b) the lagged-Fibonacci based generators (ACG, SWB, PSWB) all fail Diehard's
'Birthday spacings test', for reasons having to do with their lat-
tice structure.
These generators are only conditionally recommended.
c) The rest of the 32-bit generators (i.e. generators that fill all 32 bits
of an unsigned int) pass all tests, and are recommended at this time.
(Note that while a test may show that a generator is bad, passing a number of
tests does not prove that a generator is good!)
d) The 31-bit generators all fail the same set of tests. Some of
these cannot be passed by a generator whose output has a 'stuck' bit.
Until I clear up with Prof. Marsaglia how to interpret these results, I
believe all the 31-bit generators are in the 'recommended' category.
However, a cautionary note: while the PMMLCG generators pass the tests,
they have a very short period ( less than 2^31 ) and should only be used
for 'toy' simulations. You don't want your generator(s) to 'go around'
and start repeating themselves !

For what it's worth, Professor L'Ecuyer recommends his own C4LCGX and C2MRG3
generators as well as Matsumoto's TT800 (the monster MT19937 hadn't been
released yet), and Prof. Marsaglia recommends his own Multiply-With-Carry
generators (MWCA, MWCB, C3MWC, RWC2, RWC8="Mother").

UTILITY OBJECTS PROVIDED:
The following objects have been defined in <random/random.m>, and are
immediately accessible from anywhere in your program:
id <MT19937>               randomGenerator;
id <UniformIntegerDist>   uniformIntRand;
id <UniformUnsignedDist>  uniformUnsRand;
id <UniformDoubleDist>     uniformDblRand;
The 3 distribution objects all draw their random numbers from the MT19937
generator, which has a period of 2^19937 (10^6001) and is quite fast.

Distribution Usage Notes

Primary Author:  Sven Thommesen
(mailto:sthomme@humsci.auburn.edu)
Swarm rel.  1.0 (random rel.  0.6)
Notes on the use of the distribution objects
Sven Thommesen <sthomme@humsci.auburn.edu>
1997-09-01
IMPROVEMENTS over v. 0.6:
One new distribution class, BernoulliDist, has been added. It returns
binary values (yes/true/1) with a given probability (while the old
RandomBitDist has a fixed 50% probability, a fair coin toss.)
Distributions now have a new create method, '+createWithDefaults: aZone'.
This method creates the distribution object, and also a new generator
object for its exclusive use. Each distribution class has a different
default generator class assigned. These generators are initialized with
STARTSEED, which by default equals the fixed value DEFAULTSEED, but will
be equal to the varying RANDOMSEED if you start your program with the
command line parameter '-varySeed'.
All distributions have code to interact with the new 'split' generators.

UniformIntegerDist and UniformUnsignedDist now allow you to set parameter
minValue equal to maxValue. In this case that value is returned every time.
UniformDoubleDist also allows this, even if the set [x,x) is mathematically
suspect ...
NormalDist and LogNormalDist now allow you to specify zero Variance, in
which case the values returned are the Mean and exp(Mean) respectively.

CHANGES since v. 0.6:
The distribution classes have changed names to where they all end
in 'Dist'. A simple search-and-replace in your code will get you
back up and running.
The strong distinction between 'frozen' and 'un-frozen' distribution
objects in v. 0.6 has been softened considerably. You may now set and
reset the default parameters as often as you wish, and you may make
calls for variates with given parameters even if different default
parameters have been set.
The generation of uniform(0,1) floating point values has been
moved from the distribution objects into the generator objects.
Thus, if all you need is a uniform(0,1) double, you have no need
of a distribution but can get what you desire from a generator.
Note that the generators fill the mantissa of a double from two
32-bit unsigned values in a different manner from v. 0.6 distributions,
so output will be a bit different in the new version.
A bug in LogNormalDist has been fixed.
The 'getState:' method has been named 'putStateInto: (void *) buffer',
and the 'setState:' method is now 'setStateFrom: (void *) buffer. A quick
search-and-replace fixes things in your code.
But note: these methods have also changed somewhat, as has the size of
the data being saved. As a result, v. 0.7 distributions will refuse to
'setStateFrom' data saved by v. 0.6 objects.
There should be fewer changes like this in the next release.

USAGE notes:
------------

Each distribution object must be assigned a random generator
on creation. You may not re-assign generators to a distribution after it
has been created. You may, however, connect more than one distribution
object to one generator, so that they end up drawing output from the
generator in an interleaved fashion. Or you may create a new generator
for each distribution object.
Each distribution has its own set of (1-2) parameters. You may deal with
these parameters in two different ways: (1) you assign a set of default
parameter values to the object on creation, and draw from the distribution
using those parameters. Or (2), you may refrain from assigning default
parameters, in which case you must specify the (possibly different) desired
parameters on each call. You can (re-)set the default parameters any time,
and you may call for a variate with specified parameter values even if
different default parameters have been set.
Just like the generator objects, the distribution objects allow you to
save and later restore their internal state.

Where I use NormalDistribution in examples below, substitute any other
distribution and its parameters as needed.
NOTE: any name that starts with 'my' is meant to designate a variable
which you have defined in your own program.

You create a distribution in one of several ways:
(a) the lazy way:
   myNormalDist = [ NormalDist createWithDefaults: [self getZone]];
This method will create a distribution object with no default
parameters set, as well as a fresh generator object connected to it. The
generator object is initialized with STARTSEED (see the discussion above).
Different distribution classes use different generators for this purpose.
(b) Without default parameters, using a simple generator:
   myNormalDist = [ NormalDist create: [self getZone]
setGenerator: mySimpleGenerator ];
'myGenerator' must of course first have been set to point to a random
generator of the 'simple' type. Note that you cannot assign a different
generator to a distribution after it has been created.

You can create the generator at the same time as the distribution:
   myNormalDist = [ NormalDist create: [self getZone]
setGenerator: [TT800gen create: [self getZone]
setStateFromSeed: 34453]          ];
(c) Without default parameters, using a split generator:
   myNormalDist = [ NormalDist create: [self getZone]
setGenerator: mySplitGenerator
setVirtualGenerator: 7 ];
or perhaps
   myNormalDist = [ NormalDist create: [self getZone]
setGenerator: [C4LCGXgen createWithDefaults: [self getZone]]
setVirtualGenerator: 99 ];
A split generator can be thought of as comprising a set of virtual
generators (streams of random numbers), and a distribution object must be
'connected' to one of these streams. You cannot re-assign the generator
or the virtual generator after a distribution object has been created.
In all these cases (a) - (c), when we want to obtain a random variate from
this distribution object we need to specify the parameters:
   myDouble = [ myNormalDist getSampleWithMean: 3.3 withVariance: 1.7];
You can use different parameters for every call. (And you can use this call
even if default parameters have been set.)

(d) With default parameters, using a simple generator:
   myNormalDist = [ NormalDist create: [self getZone]
setGenerator: mySimpleGenerator
setMean: 7.6 setVariance: 1.2 ];
(e) With default parameters, using a split generator:
   myNormalDist = [ NormalDist create: [self getZone]
setGenerator: mySplitGenerator
setVirtualGenerator: 33
setMean: 3.2 setVariance: 2.1 ];
In these cases, we do not need to specify parameters to get a random number:

myDouble = [ myNormalDist getDoubleSample ];
However, you *are* allowed to specify parameters even if default parameters
have been set.
( Of course, different distributions have different parameters: RandomBitDist
has none, the Uniform objects have minimum and maximum limit val-
ues, NormalDist
and LogNormalDist use Mean and Variance, ExponentialDist only Mean, and
GammaDist used alpha and beta. See the file random/distributions.h for the
specific methods available. )

(f) You may reset the default parameters this way, as often as you like:
[ myNormalDist setMean: 3.3 setVariance: 2.2 ];

(g) You can obtain the current values of parameters:
// Default parameters:
myDouble1 = [ myNormalDist getMean ];
myDouble2 = [ myNormalDist getVariance ];
myDouble3 = [ myNormalDist getStdDev ];
// Get a pointer to the generator object:
myOtherGenerator = [ myNormalDist getGenerator ];
// Get the number of the virtual generator (if a split generator is used):
myUnsignedValue  = [ myNormalDist getVirtualGenerator];
// Find out if default parameters have been set:
myBoolean         = [ myNormalDist getOptionsInitialized ];
// Find out how many variates the object has delivered so far:
// (The counter is an unsigned long long int, which goes up to 2^64.)
myLongLongInt     = [ myNormalDist getCurrentCount ];

(h) You can reset the variate counter and other state variables this way:
[ myNormalDist reset ];
This is most likely done in conjunction with resetting the connected
generator, using [ myGenerator setStateFromSeed: mySeedValue ];

(i) Finally, we have the InternalState protocol methods:

// Print (most of) the object's state data to a stream:
[ myNormalDist describe: myStream ];
The stream myStream may be created thus:
id myStream = [ OutStream create: [self getZone] setFileStream: stdout ]; or
id myStream = [ OutStream create: [self getZone] setFileStream: stderr ];
// Get the (class) name of the object:
myString = [ myNormalDist getName ];
// Get the object's 'magic number', used by putStateInto / setStateFrom:
myUnsigned = [ myNormalDist getMagic ];
You may save, and later restore, the internal state of a distribution object
using these methods:
// Get the size of the memory buffer needed by put-
StateInto / setStateFrom:
myUnsigned = [ myNormalDist getStateSize ];
// Extract the distribution's state data into your memory buffer:
[ myNormalDist putStateInto: myBuffer ];
// Set the distribution's state from data in a memory buffer:
[ myNormalDist setStateFrom: myBuffer ];

To illustrate, assume the following data definitions:
FILE *myFile;
const char *myFileName = "MyDistFile.bin"; // or whatever
int stateSizeD;
id stateBufD;
int status;
The following code shows how to save an object's state to disk:
(You should add your own code to deal with disk file errors,
either aborting or printing out error messages.)
// Ask how big a buffer we need:
stateSizeD = [ myNormalDist getStateSize ];
// Allocate memory for the buffer:
stateBufD  = [[self getZone] alloc: stateSizeD];
// Ask the distribution object to put state data into the buffer:

[ myNormalDist putStateInto: (void *) stateBufD ];
// Open a disk file for output:
myFile = fopen(myFileName, "w");
if (myFile == NULL) { }; // error on open: disk full, or no permissions
// Write the state buffer to disk in binary form:
status = fwrite(stateBufD, stateSizeD, 1, myFile);
if (status < 1) { }; // error on write: disk full?
// Close the file
status = fclose(myFile);
if (status) { }; // error on close ?
// Free the memory allocated to the buffer:
[[self getZone] free: stateBufD];
// Or, for test purposes, just zero the buffer data instead:
// memset(stateBufD, 0, stateSizeD);

This code shows how to set an object's state from a disk file:
// Ask how big a buffer we need:
stateSizeD = [ myNormalDist getStateSize ];
// Allocate memory for the buffer:
stateBufD  = [[self getZone] alloc: stateSizeD];
// Open a disk file for input:
myFile = fopen(myFileName, "r");
if (myFile == NULL) { }; // error on open: file not found
// Read state data into the memory buffer:
status = fread(stateBufD, stateSizeD, 1, myFile);
if (status < 1) { }; // error on read
// Close the file:
status = fclose(myFile);
if (status) { }; // error on close
// Ask the distribution object to set its state from the buffer data:
[ myNormalDist setStateFrom: (void *) stateBufD ];
// Free the memory allocated to the buffer:
[[self getZone] free: stateBufD];

UTILITY OBJECTS PROVIDED:
The following objects have been defined in <random/random.m>, and are
immediately accessible from anywhere in your program:
id <MT19937>               randomGenerator;
id <UniformIntegerDist>   uniformIntRand;
id <UniformUnsignedDist>  uniformUnsRand;
id <UniformDoubleDist>     uniformDblRand;
The 3 distribution objects all draw their random numbers from the MT19937
generator, which has a period of 2^19937 (10^6001) and is quite fast.

(Interface.html)

(../random.html)

(AdvancedUsage.html)

Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-10

Random Library: Advanced Usage Guide

There should also be a general expository on the use of pseudo random number generation
in simulation, especially as applied to Swarm.

(./UsageGuide.html)

(../random.html)

(./InterfaceDesign.html)

Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-10

Random Library: Interface Design Notes

Never has a library interface been debated as this one was (and still is).  This document
will attempt to provide some of the rational for the decisions made by echoing some
of the controversial issues covered in the debates on the interface.  (These discussions
overlapped into implementation.  But, the point, here, is to give people an idea of
the complexity of the issues involved in useful pseudo-random number use in simulation.)

Issues:

Different classes for generators or variants?  Ref:  http://www.sela.co.il:8080/swtrain/new/shai/tgp.ps
Include non-recommended generators?
Seed vs.  State for generators?
What is "state" and how do we handle it?
Larger issue of debugging support via an object reporting its own configuration
  via a special method and how this relates to object state reporting and object saving.
Separate classes for separate distribution types (e.g.  double, integer, unsigned
  ::  continuous/discrete)?
Problems with the transformation from generator output to distribution output.
What precision should be supported?
Should the generator underlying a distribution be visible through the distribution?
Efficiency!
What distributions to provide?
What generators to provide?
Open vs.  Closed intervals?
Programmed default generators, seeds, and states?
Programming by committee?  (a.k.a.  Software process!)
Shorthand create methods?
Potential phase optimizations?
Random number streams, syncing limit cycles, and proper simulation vs.  code debugging.
  (This is a HOT ONE.)
Library interchangeability.
These are just the questions and issues.  Some addition should follow (when there's
time) addressing each issue and giving rationale for what we chose.  But, that's a
big job.

(AdvancedUsage.html)
(../random.html)
(Implementation.html)
         Marcus G. Daniels <mgd@santafe.edu>
         (mailto:mgd@santafe.edu)
         Last modified:  1998-01-10

Random Library: Implementation Notes

The generators supplied with this release have been subjected to statistical testing
using George Marsaglia's Diehard tests as well as John Walker's entropy tests (ENT).
The results of these tests are summarized in the document $(SWARMHOME)/src/random/docs/doc.quality.generators.
Other properties of the generators are summarized in $(SWARMHOME)/src/random/docs/generators.table.
Some notes on how to choose a generator for your simulation are found in $(SWARMHOME)/src/random/docs/CHOOSING.A.GENERATOR.
The ENT test is included in the tarball of test programs found at the Swarm web site.
The Diehard tests are copyright and hence are not, but they can be downloaded from
the web at http://www.hku.hk/internet/randomCD.html
(http://www.hku.hk/internet/randomCD.html)
.
The distribution objects have not been statistically tested.

(./InterfaceDesign.html)

(../random.html)

(../random.html)

Marcus G. Daniels <mgd@santafe.edu>
(mailto:mgd@santafe.edu)
Last modified:  1998-01-10