Random generators and variators

API for creating random generators and variators

Linear Congruential Generator

See w:Linear Congruential Generator
Uses MMIX constants, but tunable.

Unlike libc generator (that is most likely LCG too), non-singleton, so it
provides independent streams of pseudo-random numbers.

libc (default) random generator

Uses srand()/rand() functions from standard C library

Sequental generator

Uses API of random generators, but not really random generator.
Generates sequence with start value rg_seed and in interval [0; ULLONG_MAX)

Erlang distribution

See w:Erlang distribution

Params:

Exponential distribution

See w:Exponential distribution

Params:

Normal distribution

Uses Kinderman and Monahan method

Params:

Uniform distribution

Params:

Variables

rg_libc_class, rg_seq_class, rg_devrandom_class, rg_lcg_class


Random generators

TSLOADAPI randgen_class_t rg_libc_class
TSLOADAPI randgen_class_t rg_seq_class
TSLOADAPI randgen_class_t rg_lcg_class
TSLOADAPI randgen_class_t rg_devrandom_class

Constants

RV_PARAM_OK, RV_INVALID_PARAM_NAME, RV_INVALID_PARAM_VALUE


Error codes returned by rv_set_int/rv_set_double

#define RV_PARAM_OK 0
#define RV_INVALID_PARAM_NAME   -1
#define RV_INVALID_PARAM_VALUE  -2

RV_PARAM_DOUBLE, RV_PARAM_NULL, RV_PARAM_INT


Random variator parameter types

#define RV_PARAM_NULL   0
#define RV_PARAM_INT    1
#define RV_PARAM_DOUBLE 2

Functions

rg_destroy, rg_create

public

LIBEXPORT randgen_t* rg_create(randgen_class_t* class, uint64_t seed)
LIBEXPORT void rg_destroy(randgen_t* rg)

rg_generate_int

public


Generates integer with uniform distribution in range

STATIC_INLINE uint64_t rg_generate_int(randgen_t* rg) 

rg_generate_double

public


Generates double with uniform distribution in range

LIBEXPORT double rg_generate_double(randgen_t* rg)

rg_init_dummy, rg_destroy_dummy

public

LIBEXPORT int  rg_init_dummy(randgen_t* rg)
LIBEXPORT void rg_destroy_dummy(randgen_t* rg)

randgen_unregister, randgen_register

public

LIBEXPORT int randgen_register(module_t* mod, randgen_class_t* class)
LIBEXPORT int randgen_unregister(module_t* mod, randgen_class_t* class)

rv_destroy, rv_create

public

LIBEXPORT randvar_t* rv_create(randvar_class_t* class, randgen_t* rg)
LIBEXPORT void rv_destroy(randvar_t* rv)

rv_set_int

public

STATIC_INLINE int rv_set_int(randvar_t* rv, const char* name, long value) 

rv_set_double

public

STATIC_INLINE int rv_set_double(randvar_t* rv, const char* name, double value) 

rv_variate_double

public

STATIC_INLINE double rv_variate_double(randvar_t* rv) 

rv_destroy_dummy, rv_set_int_dummy, rv_init_dummy, rv_set_double_dummy

public

LIBEXPORT int rv_init_dummy(randvar_t* rv)
LIBEXPORT void rv_destroy_dummy(randvar_t* rv)
LIBEXPORT int rv_set_int_dummy(randvar_t* rv, const char* name, long value)
LIBEXPORT int rv_set_double_dummy(randvar_t* rv, const char* name, double value)

randvar_register, randvar_unregister

public

LIBEXPORT int randvar_register(module_t* mod, randvar_class_t* class)
LIBEXPORT int randvar_unregister(module_t* mod, randvar_class_t* class)

randgen_fini, randgen_init

public

LIBEXPORT int randgen_init(void)
LIBEXPORT void randgen_fini(void)

tsobj_randgen_class_format, tsobj_randvar_class_format

public

LIBEXPORT tsobj_node_t* tsobj_randgen_class_format(randgen_class_t* rg_class)
LIBEXPORT tsobj_node_t* tsobj_randvar_class_format(randvar_class_t* rv_class)

tsobj_randvar_proc, tsobj_randgen_proc

public

LIBEXPORT randgen_t* tsobj_randgen_proc(tsobj_node_t* node)
LIBEXPORT randvar_t* tsobj_randvar_proc(tsobj_node_t* node, randgen_t* rg)

Types

typedef struct randgen

typedef struct randgen {
    struct randgen_class* rg_class;
    uint64_t rg_seed;

    void* rg_private;
} randgen_t;

typedef struct randgen_class


Random generator class.

To create new generator class, initialize head members with RG_CLASS_HEAD
and set pointers to functions:

randgen_class_t rg_my_class = {
        RG_CLASS_HEAD("my", B_FALSE, max),
        rg_init_my,
        rg_destroy_my,
        rg_generate_int
};

Note that TSLoad is not a cryptographic software, so predictability of PRNGs is not
a concern. It even have sequental generator that generates numbers as N+1 where
N is last value.

Each random generated value is uint64_t. Real representation is irrelevant, i.e. for
/dev/urandom generator it is just a sequence of 8 bytes consequently read from device.
All conversion/limiting is done on a consumer side.

Random genrators should have uniform distribution in interval 0, rg_class->rg_max)
To apply different distribution, use random variators.

from TSLoad Core (libtsload) this field is set NULL

MEMBERS

typedef struct randgen_class {
    AUTOSTRING char* rg_class_name;
    
    boolean_t rg_is_singleton;
    atomic_t  rg_ref_count;
    randgen_t* rg_object;

    uint64_t rg_max;
    
    struct randgen_class* rg_next;
    module_t* rg_module;

    int  (*rg_init)(randgen_t* rg);
    void (*rg_destroy)(randgen_t* rg);

    uint64_t (*rg_generate_int)(randgen_t* rg);
} randgen_class_t;

typedef struct randvar

typedef struct randvar {
    randgen_t*    rv_generator;
    struct randvar_class* rv_class;
    void* rv_private;
} randvar_t;

typedef struct randvar_class


Random variator class

Random variators are not generating numbers. They take it from upper-level
generator and modify it so probability funciton will conform desired distribution.

Random variators may have parameters of distribution settable via rv_set_int() and
rv_set_double() and described in rv_params (and of course in documentation).

Unlike random generators, variators work with double-precision floating point numbers
(double type) distributed in

Head members are initialized with RV_CLASS_HEAD()

MEMBERS

typedef struct randvar_class {
    AUTOSTRING char* rv_class_name;
    struct randvar_class* rv_next;
    module_t* rv_module;
    
    struct tsload_param* rv_params;
    
    int (*rv_init)(randvar_t* rv);
    void (*rv_destroy)(randvar_t* rv);

    int (*rv_set_int)(randvar_t* rv, const char* name, long value);
    int (*rv_set_double)(randvar_t* rv, const char* name, double value);

    double (*rv_variate_double)(randvar_t* rv, double u);
} randvar_class_t;