RandomZZStream

© 2010 John Abbott
GNU Free Documentation License, Version 1.2



CoCoALib Documentation Index

User documentation for RandomZZStream

The class RandomZZStream is for representing generators of (independent) uniformly distributed random integers in a given range; the range is specified when creating the generator (and cannot later be changed). See also RandomLongStream for information about generating random machine integers, and RandomBitStream for information about generating random bits.

There are three ways of creating a new RandomZZStream object:

    RandomZZStream RZS1(lo,hi);      // seeded with 1 by default
    RandomZZStream RZS2(lo,hi, n);   // seed generator with abs(n)
    RandomZZStream RZS3(lo,hi, 0);   // seed generator from current time

Each generator will produce values uniformly ditributed in the range from lo to hi (with both extremes included). An ERR::BadArg exception is thrown if lo >= hi; the case lo == hi is allowed.

The third argument is for seeding the generator. Seeding from current time will produce different results each time the program is run; this is likely desirable unless you're trying to debug a randomized algorithm. Conversely, if you create more than one RandomBitStream object with the same parameters (including the seed), they will each produce exactly the same sequence of numbers.

Once you have created a RandomZZStream you may perform the following operations on it:

    *RZS             // get the current value of RZS
    ++RZS            // advance to next value of RZS.
    RZS++            // advance to next value of RZS **INEFFICIENTLY**.
    sample(RZS)      // advance RZS and then return new value; same as ``*++RZS``
    out << RZS       // print some information about RZS.
    RZS.myIndex()    // number of times RZS has been advanced,
                        same as the number of random values generated.

Note that a RandomZZStream supports input iterator syntax.

You may assign or create copies of RandomZZStream objects; the copies acquire the complete state of the original, so will go on to produce exactly the same sequence of bits as the original will produce.

Maintainer documentation for RandomZZSteam

The idea is very simple: use the pseudo random number generator of GMP to generate a random large integer in the range 0 to myRange-1 (where myRange was set in the ctor to be 1+myUpb-myLwb) and then add that to myLwb. The result is stored in the data member myValue so that input iterator syntax can be supported.

There are two "non essential" data members: mySeed and myCounter. I put these in to help any poor blighter who has to debug a randomized algorithm, and who may want to "fast forward" the RandomZZSteam to the right place.

The data member myState holds all the state information used by the GMP generator. Its presence makes the ctors, dtor and assignment messier than they would have been otherwise.

The advancing and reading member functions (i.e. operator++ and operator*) are inline for efficiency, as is the sample function.

The data members myLwb, myUpb and myRange are morally constant, but I cannot make them const because I wanted to allow assignment of RandomZZStream objects.

Bugs, Shortcomings and other ideas

Should the syntax for seeding from current time be more visibly different from the other ctor calls?

It might be neater to put ++myCounter inside myGenValue, though this would mean that myCounter gets incremented inside the ctor.

Should sample advance before or after getting the value?

Is the information printed by myOutputSelf adequate? Time will tell.

Is there a better way of writing the four ctors without repeating many lines of essentially identical source code?