[ThinAir Home] [Table of Contents] [Choosing a Random Number Generator] [Abstract Classes]

5 The Class Interfaces

A library is only as good as its interface. A powerful interface often requires a learning curve. A simple interface limits sophisticated usage of the library. ThinAir solves this problem by providing three different interfaces, each with different strengths and weaknesses. The main interface to ThinAir is provided by the base class of the library, RandomGenerator. This interface is powerful and easy to use. Since most C and C++ programmers are familiar with the rand() function interface, ThinAir provides this interface. However, the rand() interface is not very powerful or flexible. ThinAir also provides an interface based on function objects.

5.1 The RandomGenerator Interface

  The interface for all of the PRNG classes in the ThinAir library is defined by the RandomGenerator abstract base class. This class is implemented in the files randgen.h and randgen.cpp. The constructor for the class has the following prototype:

RandomGenerator( void )

Does nothing.

The class also provides default implementation for some of the more general member functions. The members of this interface are

size_rand      MaxRandom() const;

Returns the largest number that a given PRNG can ever generate.

BOOL      bad( void ) const;

This function returns true if the generator is unable to function properly. Most algorithm-based generators will always return false. This member function is most useful for generators which require some resource to run. These generators would return true from bad() if they are unable to acquire the needed resource.

size_rand      IntSeed( size_rand seed );

Modifies a generator in a class-specific way based on a single number. If possible, IntSeed() should have the same effect every time a particular seed value is used.

size_rand      Number();

Returns a random number between 0 and MaxRandom(), inclusive.

double      FloatNumber();

Returns a random double number greater than or equal to 0.0 and less than 1.0.

size_rand      LimitedNumber( size_rand limit );

Returns a random number between 0 and limit-1, inclusive.

void      Reset();

Resets the generator to its initial conditions.

RandomGenerator      *ReCreate() const;

Clones the generator in its initial state.

RandomGenerator      *Clone() const;

Clones the generator complete with its current state.

  When performing simulations, it is often useful to rerun the same sequence of random numbers through two different tests to compare responses. The RandGenToken class allows you to save the current state of a PRNG object for later restoration. This is an instance of the Token design pattern described in [3]. The member functions of RandomGenerator that support this pattern are

RandGenToken      CreateToken() const;

Creates a RandGenToken object that stores the current state of the PRNG object.

int      SetToken( const RandGenToken &pToken );

Restores the PRNG object to the state saved in pToken.

Additionally, the token classes also have a useful public interface:

string      CreateInitString() const;

Creates an initialization string that describes the initial state of the generator associated with this token.

int      Initialize( const string &InitString );

Takes the initialization string created by CreateInitString() and reinitializes the token.

int      Initialize( istream &InitStream );

Same as above except that the function is passed an input stream. This is the more flexible of the two functions, but is often not as convenient.

The RandGenToken class supports extraction from and insertion into streams. In addition, the token classes have a pair of protected functions that support the stream functions.

istream      &operator\gt\gt( istream &is, RandGenToken &Token );

Extracts the token from the istream is using Read().

ostream      &operator\lt\lt( ostream &os, RandGenToken const &Token );

Inserts the token into the ostream os using Print().

void      Print( ostream &os ) const;

Writes the token's internal data to the ostream os.

void      Read( istream &is );

Reads the token's internal data from the istream is.

Each kind of PRNG has a token class derived from RandGenToken. However, the definition of the token classes are private to the PRNG class they support. There should never be any good reason for digging into the token class definitions, except for the creation of new generator types.

5.2 The rand() Interface

Many programs written in C/C++ that need random number sequences use the standard library rand() function and its support functions. What you may not have realized is that this function uses an implementation-defined generator that may or may not be any good. So what do you do if your code already uses rand(), and you would like to try ThinAir?

This library contains a set of functions to duplicate the rand() function interface wrapped around one of the classes from this library. The idea is to provide the interface an average C programmer might find familiar, with a simple method of changing the generator behind it.

By including the ThinAir rand_rng.h header file, you can have this interface for any random number class you choose. To use one of these classes with the rand() interface, you must call the function setup_rand() with a heap-based pointer to your chosen generator as the argument.

Like the standard library version of rand(), the PRNG class library provides the following interface, plus one extra function:

RAND_MAX

The largest number that the current generator can return.

size_rand      rand();

Returns a number between 0 and RAND_MAX.

size_rand      random( size_rand lim );

Returns a number between 0 and lim.

size_rand      srand( size_rand seed );

Applies the class-specific function IntSeed() to the current generator object with the argument seed. This should change the output sequence in some defined way.

void      randomize( void );

Calls the srand() function in a simple fashion to change the current generator. Like the standard library equivalent, randomize() uses the current time as a seed.

void      setup_rand( RandomGenerator *pRNG );

Plugs a new generator into the rand() interface. This function expects a pointer to a heap-based PRNG object.

5.3 The Function Object Interface

With support for the STL being written into the C++ standard (see [5]), function objects are becoming an important idea to consider. The STL supports a random_shuffle() algorithm that accepts a random number generator function object as an argument. In order to support this algorithm, the PRNG class library provides a Function Object interface for the classes. This interface also supplies other function objects which you may find useful. This interface is provided by five classes, which are defined in the file randfunc.h. All of these objects are used by calling the operator() member function.

Much of the time you want to use a PRNG the same way over and over again. These classes simplify this approach to using a PRNG.

Each of the Function Objects expects a pointer to a PRNG object that was allocated from the heap. Don't pass the address of a stack-based PRNG object to these functions. After construction, the Function Object owns the PRNG object, so you do not need to delete the PRNG.

5.3.1 RNGFuncAdaptor

This function object class defines an object which returns a random number from a particular PRNG object. The operator() member function calls the Number() member function of its PRNG. The constructor for this class has the following prototype:

explicit RNGFuncAdaptor( RandomGenerator *pRNG )

Requires a pointer to a heap-based PRNG object. The RNGFuncAdaptor object owns this PRNG and deletes it when the object is destroyed.

5.3.2 RNGFuncAdaptorFloat

This function object class defines an object which returns a random double greater than or equal to 0.0 and less than 1.0. The operator() member function calls the FloatNumber() member function of this PRNG. The constructor for this class has the following prototype:

explicit RNGFuncAdaptorFloat( RandomGenerator *pRNG )

Requires a pointer to a heap-based PRNG object. The RNGFuncAdaptorFloat object owns this PRNG and deletes it when the object is destroyed.

5.3.3 RNGFuncAdaptorLimit

This function object class defines an object which returns a number between 0 and a programmer-supplied limit value. The operator() member function calls the LimitedNumber() member function of this PRNG passing the selected limit. This class also has a second operator() member function that expects a single argument. This member function uses the supplied argument instead of the stored limit when calling LimitedNumber(). The constructor for this class has the following prototype:

RNGFuncAdaptorLimit( RandomGenerator *pRNG, size_rand limit )

Requires a pointer to a heap-based PRNG object. The RNGFuncAdaptorLimit object owns this PRNG and deletes it when the object is destroyed. The limit argument defines the range of values returned by the operator() member function.

5.3.4 RNGFuncAdaptorPercentLikely

This function object class defines an object which returns a non-zero result a programmer-supplied percentage of the time. The operator() member function returns a non-zero value percent times out of a hundred on average. This class also has a second operator() member function that expects a single argument. This member uses the supplied percent instead of the stored one. The constructor for this class has the following prototype:

RNGFuncAdaptorPercentLikely( RandomGenerator *pRNG, unsigned percent )

Requires a pointer to a heap-based PRNG object. The RNGFuncAdaptorPercentLikely object owns this PRNG and deletes it when the object is destroyed.

5.3.5 RNGFuncAdaptorRange

This function object class defines an object which returns a number between two programmer-supplied limits. The operator() member function returns a value between lower and upper, inclusive. The constructor for this class has the following prototype:

RNGFuncAdaptorRange( RandomGenerator *pRNG, size_rand lower, size_rand upper )

Requires a pointer to a heap-based PRNG object. The RNGFuncAdaptorRange object owns this PRNG and deletes it when the object is destroyed. The arguments lower and upper define the range of values that can be returned by the operator() member function.


For further information, contact G. Wade Johnson (gwadej@anomaly.org).

© 1997 G. Wade Johnson. All rights reserved.
http://www.anomaly.org/ThinAir/intrface.html