# Formats for User-Designed Generators

To register a user-designed basic generator using RegisterBrng function, you need to pass the pointer iBrng to the integer-value implementation of the generator; the pointers sBrng and dBrng to the generator implementations for single and double precision values, respectively; and pass the pointer InitStream to the stream initialization routine. See below recommendations on defining such functions with input and output arguments. An example of the registration procedure for a user-designed generator can be found in the respective directory of VSL examples.

The respective pointers are defined as follows:

typedef int(*InitStreamPtr)( int method, VSLStreamStatePtr stream, int n, const unsigned int params[] );

typedef int(*sBRngPtr)( VSLStreamStatePtr stream, int n, float r[], float a, float b );

typedef int(*dBRngPtr)( VSLStreamStatePtr stream, int n, double r[], double a, double b );

typedef int(*iBRngPtr)( VSLStreamStatePtr stream, int n, unsigned int r[] );

## InitStream

C:

int MyBrngInitStream( int method, VSLStreamStatePtr stream, int n, const unsigned int params[] )

{

/* Initialize the stream */

...

} /* MyBrngInitStream */

## Description

The initialization routine of a user-designed generator must initialize stream according to the specified initialization method, initial conditions params and the argument n. The value of method determines the initialization method to be used.

- If method is equal to 1, the initialization is by the standard generation method, which must be supported by all basic generators. In this case the function assumes that the stream structure was not previously initialized. The value of n is used as the actual number of 32-bit values passed as initial conditions through params. Note, that the situation when the actual number of initial conditions passed to the function is not sufficient to initialize the generator is not an error. Whenever it occurs, the basic generator must initialize the missing conditions using default settings.

- If method is equal to 2, the generation is by the leapfrog method, where n specifies the number of computational nodes (independent streams). Here the function assumes that the stream was previously initialized by the standard generation method. In this case params contains only one element, which identifies the computational node. If the generator does not support the leapfrog method, the function must return the error code VSL_ERROR_LEAPFROG_UNSUPPORTED.

- If method is equal to 3, the generation is by the block-splitting method. Same as above, the stream is assumed to be previously initialized by the standard generation method; params is not used, n identifies the number of skipped elements. If the generator does not support the block-splitting method, the function must return the error code VSL_ERROR_SKIPAHEAD_UNSUPPORTED.

For a more detailed description of the leapfrog and the block-splitting methods, refer to the description of LeapfrogStream and SkipAheadStream, respectively.

Stream state structure is individual for every generator. However, each structure has a number of fields that are the same for all the generators:

C:
`typedef struct`
`{`
`unsigned int Reserved1[2];`
`unsigned int Reserved2[2];`
`[fields specific for the given generator]`
`} MyStreamState;`

The fields Reserved1 and Reserved2 are reserved for private needs only, and must not be modified by the user. When including specific fields into the structure, follow the rules below:

- The fields must fully describe the current state of the generator. For example, the state of a linear congruential generator can be identified by only one initial condition;

- If the generator can use both the leapfrog and the block-splitting methods, additional fields should be introduced to identify the independent streams. For example, in `LCG(a, c, m)`, apart from the initial conditions, two more fields should be specified: the value of the multiplier ak and the value of the increment (`ak-1)c/(a-1`).

For a more detailed discussion, refer to [Knuth81], and [Gentle98]. An example of the registration procedure can be found in the respective directory of VSL examples.

## iBRng

C:

int iMyBrng( VSLStreamStatePtr stream, int n, unsigned int r[] )

{

int i; /* Loop variable */

/* Generating integer random numbers */

/* Pay attention to word size needed to

store only random number */

for( i = 0; i < n; i++)

{

r[i] = ...;

}

/* Update stream state */

...

return errcode;

} /* iMyBrng */

### Note

When using 64 and 128-bit generators, consider digit capacity to store the numbers to the random vector r correctly. For example, storing one 64-bit value requires two elements of r, the first to store the lower 32 bits and the second to store the higher 32 bits. Similarly, use 4 elements of r to store a 128-bit value.

## sBRng

C:

int sMyBrng( VSLStreamStatePtr stream, int n, float r[], float a, float b )

{

int i; /* Loop variable */

/* Generating float (a,b) random numbers */

for ( i = 0; i < n; i++ )

{

r[i] = ...;

}

/* Update stream state */

...

return errcode;

} /* sMyBrng */

## dBRng

C:

int dMyBrng( VSLStreamStatePtr stream, int n, double r[], double a, double b )

{

int i; /* Loop variable */

/* Generating double (a,b) random numbers */

for ( i = 0; i < n; i++ )

{

r[i] = ...;

}

/* Update stream state */

...

return errcode;

} /* dMyBrng */

Parent topic: Advanced Service Routines