Skip to content

Instantly share code, notes, and snippets.

@senevoldsen
Created August 27, 2019 15:34
Show Gist options
  • Save senevoldsen/e1bafbf2efcd49497e5e238ec82b111b to your computer and use it in GitHub Desktop.
Save senevoldsen/e1bafbf2efcd49497e5e238ec82b111b to your computer and use it in GitHub Desktop.
Acorn random number generator
// 2**21 leaving more than enough for safe integer addition
#define MF_ACORN_M 2097152
#define MF_ACORN_M_RECIP 4.76837158203125e-07
// Higher better and slower, but keep max 20
#define MF_ACORN_DEFAULT_K 6
// This should be 0 < y0 < M, and relative prime wrt. to M meaning just odd since M is power of two.
#define MF_ACORN_DEF_Y0 682777
MF_ACORN_TEST_K = [1406504, 41542, 1738859, 883892, 220285, 2090629, 398606, 996019, 1191661, 1076927, 1344894, 411434, 1380805, 1099101, 820216, 1442075, 1593105, 1145902, 38279, 1782955];
MF_ACORN_TEST_K resize MF_ACORN_DEFAULT_K;
/*
Returns next number [0, 1)
*/
MF_fnc_acornNext = {
params ["_prg"];
private _K_last = (_prg select 0) + 1; // + 2 - 1
for "_i" from 2 to _K_last do {
private _lower = _prg select (_i - 1);
private _prev = _prg select _i;
// Floor should never be necessary since we should in integer domain.
private _next = (_lower + _prev) % MF_ACORN_M;
_prg set [_i, _next];
};
// Note even if you just want integers, you can not skip this step
// since the integers may not be evenly distributed.
(_prg select _K_last) * MF_ACORN_M_RECIP;
};
/*
Seed: where 0 < seed < M and relative prime to M.
or just "RANDOM"
_K:
- NUMBER - the order of the generator, _K > 1, random initial parameters will be chosen
- ARRAY - the initial K values (each value must be 0 <= K_i < M) (does not have to be relative prime)
NOT including the seed
*/
MF_fnc_initAcornPRG = {
params [
["_seed", MF_ACORN_DEF_Y0],
["_K", MF_ACORN_DEFAULT_K]
];
if (_seed isEqualTo "RANDOM") then {
_seed = (floor random (MF_ACORN_M / 2)) * 2 + 1;
};
if (_K isEqualType 0) then {
private _temp = [];
for "_i" from 1 to _K do {
_temp pushBack (floor (random MF_ACORN_M));
};
_K = _temp;
};
private _prg = [count _K, _seed];
_prg append _K;
_prg;
};
/*
Generate histogram
*/
MF_fnc_acornHistogram = {
params [
"_prg",
"_count",
["_numBuckets", 10]
];
private _buckets = [];
for "_i" from 1 to _numBuckets do {
_buckets pushBack 0;
};
for "_i" from 1 to _count do {
private _b = floor (([_prg] call MF_fnc_acornNext) * _numBuckets);
private _before = _buckets select _b;
_buckets set [_b, _before + 1];
};
_buckets;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment