Created
August 27, 2019 15:34
-
-
Save senevoldsen/e1bafbf2efcd49497e5e238ec82b111b to your computer and use it in GitHub Desktop.
Acorn random number generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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