Interface with Pointer Checking
In this section, we give detailed descriptions of each SPRNG function call with the interface with pointer checking. It is invoked by defining the macro CHECK_POINTERS before including a SPRNG header file. This interface would typically be used while debugging a program with more than one random number stream per process. The different streams are distinguished by unique ID's, which are implemented as pointers to memory locations where the states of the respective streams are stored. Most SPRNG functions take this stream ID as an argument. If the user passes an invalid ID as an argument, then this can lead to unpredictable behavior by SPRNG. This interface first checks to see if the ID is valid before using it. In case an invalid ID is used, it responds as explained in the function descriptions below. A determined user can however subvert this checking system by freeing a stream directly without invoking the free_sprng function.Users should note that this interface can slow down the program moderately. Its use is therefore recommended only while debugging. The default interface is identical to this interface, except that it is does not check for the validity of the ID's, and hence can be used once debugging has been completed.
Pointers for FORTRAN users
The different random number streams available on a process are distinguished by unique ID's, which are implemented as pointers to the memory locations where the states of the respective streams are stored. Since standard FORTRAN 77 does not have a pointer type, we can store a pointer as an integer of the same size as a C pointer. We have defined a macro called SPRNG_POINTER in the file sprng_f.h that automatically defines an integer of the correct size on the platforms on which SPRNG is supported. A FORTRAN programmer can then use the type SPRNG_POINTER just as if it were a FORTRAN data type. However, this applies only if the FORTRAN program is compiled with the same flags as given in the make file that comes with SPRNG.Terminology
In the following description, an argument marked as IN indicates that the argument, or array elements pointed to by that argument, are read by the function, but not modified. OUT indicates that the argument, or array elements pointed to by that argument, are written into by the function, but that its values are not used by the function. Arguments that are both read and modified are denoted by INOUT.SPRNG Functions
We describe below the SPRNG function calls available in the interface with pointer checking. For each function, the C call is given first, followed by the FORTRAN call. The data type preceding the function name is the type returned by the function. The data types preceding the arguments to the functions are the data types of the corresponding function arguments.
- 1. init_sprng
- int *init_sprng(int streamnum, int nstreams, int seed, int param)
- SPRNG_POINTER init_sprng(integer streamnum, integer nstreams, integer seed, integer param)
IN streamnum, IN nstreams, IN seed, IN param.
- init_sprng initializes random number streams.
nstreams is the number of distinct streams that will be initialized across all the processes and must be greater than 0. Otherwise it is reset to 1 and a warning message is sent to stderr stating that the number of streams has been reset.
streamnum
is the stream number, typically the process number, and must be in [0,nstreams-1]. If it is not in the acceptable range, then an error message is sent to stderr and the function returns a NULL pointer. Note that the number of independent streams for each type of generator is limited (but at least 105). Ifstreamnum
is larger than this number, then a warning message is sent to stderr stating that the independence of streams cannot be guaranteed.
seed is the seed to the random number generator. It is not the starting state of the sequence; rather, it is an encoding of the starting state. It is acceptable (and recommended) to use the same seed for all the streams. Distinct streams are returned based on their seed and the stream number. Only the 31 least significant bits of seed are used in determining the initial starting state of the stream. Higher order bits that are set will be ignored. No warning message is printed if the higher order bits are set.
The argument param selects the appropriate parameters (for example, the multiplier for a Linear Congruential Generator or the lag for a Lagged Fibonacci Generator). The macro SPRNG_DEFAULT, defined in the SPRNG header files, can be used to choose the default parameters. If an invalid parameter is passed to this function, then a warning message is sent to stderr and the default parameter is used.
init_sprng returns the ID of the stream when it completes successfully. If it fails due to incorrect arguments or inability to allocate memory, then an error message is sent to stderr and a NULL pointer is returned.
Example
- 2. sprng
- double sprng(int *stream)
- real*8 sprng(SPRNG_POINTER stream)
INOUT stream.
- stream is the ID of the stream from which the next random number in [0,1) is returned by this function. This argument must have been obtained by a prior call to init_sprng, spawn_sprng or unpack_sprng. In case stream is an invalid ID, this function returns -1.0.
If FORTRAN programmers wish to obtain real*4 numbers, or C programmers float numbers, instead of the double precision default, then they should define the macro FLOAT_GEN before including a SPRNG header file.
Example
- 3. isprng
- int isprng(int *stream)
- integer isprng(SPRNG_POINTER stream)
INOUT stream.
- stream is the ID of the stream from which the next random integer in [0,231) is returned by this function. This argument must have been obtained by a prior call to init_sprng, spawn_sprng or unpack_sprng. In case stream is an invalid ID, this function returns -1.
Callingisprng
is equivalent to multiplying the result ofsprng
by 231 and truncating to an integer. Calls tosprng
andisprng
can be interleaved.
Example
- 4. print_sprng
- int print_sprng(int *stream)
- integer print_sprng(SPRNG_POINTER stream)
IN stream .
- The user may wish to print information about streams without printing the entire state, for example after initialization. This is typically done when the user wishes to record information which can later be used to identify the random number stream used in the computations. This information can be obtained by a call to print_sprng with the ID of the stream as argument. stream must have been obtained by a prior call to init_sprng, spawn_sprng or unpack_sprng. In case stream is an invalid ID, this function returns 0. Otherwise it returns a non-zero value.
Example
- 5. make_sprng_seed
- int make_sprng_seed()
- integer make_sprng_seed()
- This function produces a new seed using system date and time information. It will typically be used when the programmer wishes to initialize with a different seed every time the program is run. User should note that both the Lagged Fibonacci Generators require the use of the same seed for each stream in order to guarantee their independence. In order to ensure this on a parallel computer, they should install the MPI version of SPRNG and define the macro USE_MPI before including a SPRNG header file. This function will then involves some inter-processor communication.
If the user has installed the MPI version of the library but has not defined the macro USE_MPI, then the seed could be different on the different processes. No warning message is printed. If the user has not installed the MPI version of the library but includes the macro USE_MPI, then link time errors will be reported by the compiler.
Note: If users have installed the MPI version of the library and defined the macro USE_MPI, then they must call MPI_Init before making calls to make_sprng_seed. The user should also call MPI_Finalize later. SPRNG does not make either of these calls. If any process calls make_sprng_seed, then users should ensure that all their processes call this function, since collective MPI operations are performed here.
Example
- 6. pack_sprng
- int pack_sprng(int *stream, char **buffer)
- integer pack_sprng(SPRNG_POINTER stream, character fbuffer)
IN stream, OUT buffer, OUT fbuffer.
- This function packs the state of the stream with ID stream into an array and returns the number of bytes actually required for the storage. stream must have been obtained by a prior call to init_sprng, spawn_sprng or unpack_sprng. In case stream is an invalid ID, this function returns 0.
fbuffer should be the first element of an array of size MAX_PACKED_LENGTH bytes, where MAX_PACKED_LENGTH is a macro defined in "sprng_f.h" and "sprng.h". If the memory in the array is insufficient, undetected errors could occur. It might also lead to segmentation faults. In the C interface, the programmer need not allocate memory. SPRNG allocates memory for the array and has the result stored in *buffer.
Calls to this function in C or FORTRAN involve memory allocation within this function. In case of insufficient memory, an error message is sent to stderr and the value 0 is returned.
This function can be used for check-pointing, where the programmer packs the state of the stream into an array and then saves it to a file. This state can later be retrieved by calling unpack_sprng, which is explained below. pack_sprng can also be used to pass a stream to another process. That process will unpack the packed array to obtain the stream.
Note: SPRNG does not free the memory associated with a stream when it packs it. If users do not plan to use the stream that has been packed, then they can explicitly call free_sprng in order to free the memory.
Example
- 7. unpack_sprng
- int *unpack_sprng(char *buffer)
- SPRNG_POINTER unpack_sprng(character fbuffer)
IN buffer, IN fbuffer.
- This function recreates a stream given the array buffer or fbuffer, which was used to store the stream's state through a call to the function pack_sprng. An ID for the recreated stream is returned. Note that this ID is unrelated to the previous ID of the stream before it was packed, though the states are the same.
Calls to this function involve memory allocation. In case sufficient memory was not obtained, an error message is sent to stderr and the NULL pointer is returned. The packed string must be the state of a valid stream. If it is not, the error may not necessarily be detected by SPRNG. If an error is detected, then an error message is sent to stderr and a NULL pointer is returned.
Example
- 8. free_sprng
- int free_sprng(int *stream)
- integer free_sprng(SPRNG_POINTER stream)
INOUT stream.
- This function frees the memory used to store information concerning the random number stream identified by the stream ID
stream
. The stream's ID is then no longer valid. stream must have been obtained by a prior call to init_sprng, spawn_sprng or unpack_sprng. In case stream is an invalid ID, this function returns -1.
free_sprng returns the current number of streams available on the process.
Example
- 9. spawn_sprng
- int spawn_sprng(int *stream, int nspawned, int ***newstreams)
- integer spawn_sprng(SPRNG_POINTER stream, integer nspawned, SPRNG_POINTER fnewstreams)
INOUT stream, IN nspawned, OUT newstreams, OUT fnewstreams .
- Some times, for example in branching processes, it is necessary to spawn new streams from an old one. This function creates new random number streams when given a stream ID stream and the number of new streams nspawned to be spawned.
stream must have been obtained by a prior call to init_sprng, spawn_sprng or unpack_sprng. In case stream is an invalid ID, this function returns 0.
nspawned is the number of streams that will be spawned and must be greater than 0. Otherwise it is reset to 1 and a warning message is sent to stderr stating that the number of streams has been reset. In the unlikely event of an extremely large number of streams being spawned, SPRNG cannot guarantee the independence of the different streams. In this case, a warning message is sent to stderr. We may also change the seed of the new streams spawned in this case to make it less likely that different streams will overlap.
fnewstreams is the first element of an array of length at least nspawned in which the ID's of the new streams will be stored. In the C interface, SPRNG allocates memory for the array and makes *newstreams point to it.
spawn_sprng returns the number of streams successfully spawned. If the function fails due to an inability to allocate memory, then the value returned is less than nspawned. If the function fails due to an incorrect value of stream, then the returned value is 0.
Note: If users spawn too often, then the available set independent streams can get exhausted, depending on the random number generator used. Therefore some caution must be used in spawning streams.
Example