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 an instance of a custom random number generator.
You can set a custom type of random number generator as the default type of random number generator.
The function qsmm_rng_create creates an instance of a default random number generator.
The functions qsmm_actor_create and qsmm_create call qsmm_rng_create if the rng field 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.
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.
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.
This is a type for the pointer to an abstract proxy function. The following declaration corresponds to the 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 input parameters of the 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.
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 addressing 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.
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 addressing an allocated instance of a structure holding the state of a random number generator for subsequent destruction of the instance, write the following line of code:
rng_state_p=*((void **) in_p);
The proxy function shall return a non-negative value.
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.
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 the 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.
This structure passes input parameters of an operation of seeding a pseudo-random number generator. The structure contains the following fields.
int seed ¶A seed value.
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 the default type of random number generator, write the line of code
qsmm_set_rng_default(&rng_proxy,0);