Developer Reference for Intel® oneAPI Math Kernel Library for C

ID 766684
Date 3/22/2024
Public

A newer version of this document is available. Customers should click here to go to the newest version.

Document Table of Contents

Formats for User-Designed Generators

To register a user-designed basic generator using vslRegisterBrng 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 recommendations below 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 VS 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

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_RNG_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_RNG_ERROR_SKIPAHEAD_UNSUPPORTED.

  • If method is equal to 4, the generation is by the advanced block-splitting method. The stream is assumed to be previously initialized by the standard generation method; params is converted to MKL_UINT64[] and n is used as actual number of 64-bit values in params. If the generator does not support the advanced block-splitting method, the function must return the error code VSL_RNG_ERROR_SKIPAHEADEX_UNSUPPORTED.

For a more detailed description of the leapfrog and the block-splitting methods, refer to the description of vslLeapfrogStream, vslSkipAheadStream, and vslSkipAheadStreamEx, 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:

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 VS examples.

iBRng

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

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

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 */