TRand

TRand

Overview

Trand implements triggerable random number generator. Every time a trigger is received, it produces a new random number in a given range.

Tangled Files

trand.c and trand.h. SK_TRAND_PRIV will expose the struct contents for sk_trand.

<<trand.h>>=
#ifndef SK_TRAND_H
#define SK_TRAND_H

#ifndef SKFLT
#define SKFLT float
#endif

#ifdef SK_TRAND_PRIV
<<structs>>
#endif

<<typedefs>>
<<funcdefs>>

#endif

<<trand.c>>=
#define SK_TRAND_PRIV
#include "trand.h"

<<funcs>>

Initialization and Struct

Initialize trand with sk_trand_init. It will need an initial seed value for the internal RNG.

<<funcdefs>>=
void sk_trand_init(sk_trand *tr, unsigned long seed);

<<funcs>>=
void sk_trand_init(sk_trand *tr, unsigned long seed)
{
    <<init>>
}

The struct for trand is sk_trand.

<<typedefs>>=
typedef struct sk_trand sk_trand;

The sk_trand struct contains the RNG state, min/max ranges, and a random value that was generated last.

For optimization, a scale variable is used to scale the RNG value within range. A changed variable is also used to signal if min or max have changed, and will trigger the scale value to update (this is a version of parameter caching, but using one flag to monitor the state of two variables).

<<structs>>=
struct sk_trand {
    unsigned long rng;
    SKFLT min;
    SKFLT max;
    SKFLT val;
    SKFLT scale;
    int changed;
};

TRand will be initialized to output values between 0 and 1, with it's internal seed set to the one provided by the init function.

Note: val will be set to be 0. This means that trand will return 0 until the first trigger.

<<init>>=
tr->rng = seed;
tr->val = 0;
tr->changed = 0;
tr->min = 0;
tr->max = 1;
tr->scale = 1.0 / 2147483648L;

Parameters

TRand takes has two parameters: min and max. These set the range of the random numbers, and can be set with sk_trand_min and sk_trand_max.

<<funcdefs>>=
void sk_trand_min(sk_trand *tr, SKFLT min);
void sk_trand_max(sk_trand *tr, SKFLT max);

<<funcs>>=
void sk_trand_min(sk_trand *tr, SKFLT min)
{
    if (tr->min != min) {
        tr->min = min;
        tr->changed = 1;
    }
}

void sk_trand_max(sk_trand *tr, SKFLT max)
{
    if (tr->max != max) {
        tr->max = max;
        tr->changed = 1;
    }
}

Compute

Computed with sk_trand_compute.

<<funcdefs>>=
SKFLT sk_trand_tick(sk_trand *tr, SKFLT trig);

If a trigger happens, update the random number. If the parameters change, update the scaling.

<<funcs>>=
SKFLT sk_trand_tick(sk_trand *tr, SKFLT trig)
{
    if (trig != 0) {
        if (tr->changed) {
            tr->changed = 0;
            tr->scale = 1.0 / 2147483648L;
            tr->scale *= (tr->max - tr->min);
        }
        tr->val = tr->min + (tr->rng * tr->scale);
        tr->rng = (1103515245 * tr->rng + 12345) % 2147483648;
    }
    return tr->val;
}