Previous: , Up: Random Number Generators   [Contents][Index]


6.1.3 Custom Random Number Generators

A user-supplied function qsmm_proxy_func_t and its parameter define a custom type of random number generator. The function qsmm_rng_create_custom creates instances of custom random number generators. You can set a custom type of random number generator as the default type of random number generator. The function qsmm_rng_create creates the instances of a default random number generator. The functions qsmm_actor_create and qsmm_create call qsmm_rng_create if the field rng of qsmm_actor_desc_s or qsmm_desc_s structure is NULL.

Use the following functions to retrieve or set a user-supplied function qsmm_proxy_func_t and its parameter defining the default type of random number generator.

Function: void qsmm_get_rng_default (qsmm_proxy_func_t *rng_func_p, void **param_pp)

This function retrieves the default type of random number generator defined by a user-supplied function qsmm_proxy_func_t and its parameter. If rng_func_p is not NULL, the function sets *rng_func_p to a pointer to the user-supplied function. If the default random number generator is a standard random number generator (with a type defined when configuring the package), the function sets *rng_func_p to NULL. If param_pp is not NULL, the function sets *param_pp to a user parameter of qsmm_proxy_func_t function.

Function: void qsmm_set_rng_default (qsmm_proxy_func_t rng_func, void *paramp)

This function sets the default type of random number generator. A function rng_func and its parameter paramp define that type. If rng_func is NULL, the function qsmm_set_rng_default sets a standard random number generator (with a type defined when configuring the package) as the default random number generator.

A function that along with its user parameter defines the type of a random number generator has a prototype of an abstract proxy function. Future QSMM versions may use this abstract proxy function to perform operations on other objects.

Data type: qsmm_proxy_func_t

This is a type for the pointer to an abstract proxy function. The following declaration corresponds to this type:

typedef int
(*qsmm_proxy_func_t)(
    int cmd,
    int in_sz,
    int out_sz,
    const void *in_p,
    void *out_p,
    void *paramp
);

The argument cmd specifies the identifier of a command—an operation the proxy function shall perform. A buffer in_p with length in_sz bytes specifies the input parameters of this command. The proxy function shall store or update in a buffer out_p with length out_sz bytes the results of command invocation. The argument paramp is a user parameter specified when setting the proxy function.

On successful completion, the proxy function shall return a non-negative value. On error, the proxy function shall return a negative value. Specific interpretation of a returned value depends on an object the function represents and an operation performed by the function.

Below there is a description of a random number generator interface for implementing by a proxy function—possible cmd values, input command parameters, and the results of command invocation.

Macro: QSMM_RNG_CMD_CREATE

Create a random number generator. The proxy function shall store in a buffer out_p the pointer to an object representing the random number generator. The argument out_sz is always equal to sizeof(void *). For example, to return the pointer rng_state_p to an allocated instance of a structure holding the state of a created random number generator, write a line of code like this:

*((void **) out_p)=rng_state_p;

The proxy function can return negative error code QSMM_ERR_NOMEM indicating that there was not enough memory to allocate an object representing the random number generator. In this case, the function qsmm_rng_create or qsmm_rng_create_custom called to create the random number generator returns this error code.

Macro: QSMM_RNG_CMD_DESTROY

Destroy a random number generator. A buffer in_p holds the pointer to an object representing the random number generator. The argument in_sz is always equal to sizeof(void *). For example, to obtain the pointer rng_state_p to an allocated instance of a structure holding the state of a random number generator for subsequent destruction of this instance, write the following line of code:

rng_state_p=*((void **) in_p);

The proxy function shall return a non-negative value.

Macro: QSMM_RNG_CMD_GENERATE

Generate a random number. A buffer in_p holds the pointer to an object representing the random number generator. The argument in_sz is always equal to sizeof(void *). The proxy function shall store in a buffer out_p a generated random number uniformly distributed in the range 0 (inclusive) to 1 (exclusive). The argument out_sz is always equal to sizeof(double). For example, to return generated random number rnd, write a line of code like this:

*((double **) out_p)=rnd;

The proxy function shall return a non-negative value.

Macro: QSMM_RNG_CMD_SEED

Seed a pseudo-random number generator. A buffer in_p holds an instance of qsmm_rng_cmd_seed_in_s structure (see below) containing a random seed and the pointer to an object representing the pseudo-random number generator. The function qsmm_rng_seed receives the random seed as the second argument. The argument in_sz is always equal to sizeof(struct qsmm_rng_cmd_seed_in_s). To obtain seeding parameters, use lines of code like these:

const struct qsmm_rng_cmd_seed_in_s *const cmd_in_p=in_p;
rng_state_p=cmd_in_p->rng_object_p;

If the pseudo-random number generator does not support the seeding operation, the proxy function can return negative error code QSMM_ERR_NOTSUP. However, the function qsmm_rng_seed currently returns void and ignores this error code.

The following structure conveys the parameters of a seeding operation.

Structure: qsmm_rng_cmd_seed_in_s

This structure passes the input parameters of an operation of seeding a pseudo-random number generator. The structure contains the following fields.

Field: int seed

A seed value.

Field: void * rng_object_p

The pointer to an object representing the pseudo-random number generator.

An example proxy function implementing the random number generator interface is below.

#include <stdint.h>
#include <stdlib.h>

#include <qsmm/qsmm.h>

static int
rng_proxy(
    int cmd,
    int in_sz,
    int out_sz,
    const void *in_p,
    void *out_p,
    void *paramp
) {
    uint32_t *seed_p;
    switch (cmd) {
        case QSMM_RNG_CMD_CREATE:
            if (!(seed_p=malloc(sizeof(*seed_p)))) return QSMM_ERR_NOMEM;
            *seed_p=1;
            *((void **) out_p)=seed_p;
            break;
        case QSMM_RNG_CMD_DESTROY:
            free(*((void **) in_p));
            break;
        case QSMM_RNG_CMD_GENERATE:
            seed_p=*((void **) in_p);
            *seed_p=*seed_p*1103515245+12345;
            *((double *) out_p)=(*seed_p/65536)%32768/32768.0;
            break;
        case QSMM_RNG_CMD_SEED: {
            const struct qsmm_rng_cmd_seed_in_s *const cmd_in_p=in_p;
            seed_p=cmd_in_p->rng_object_p;
            *seed_p=cmd_in_p->seed;
            break;
        }
    }
    return 0;
}

To set this proxy function as a default random number generator, write the line of code

qsmm_set_rng_default(&rng_proxy,0);

Previous: , Up: Random Number Generators   [Contents][Index]