From 06cda473270273c7d323caf79f25bb44902363de Mon Sep 17 00:00:00 2001 From: Ray Gardner Date: Wed, 27 Mar 2024 15:37:15 -0600 Subject: [PATCH] Use random() / srandom() for toybox --- toys/pending/awk.c | 40 ++++++++++------------------------------ 1 file changed, 10 insertions(+), 30 deletions(-) diff --git a/toys/pending/awk.c b/toys/pending/awk.c index b66bb13c..f3519f68 100644 --- a/toys/pending/awk.c +++ b/toys/pending/awk.c @@ -2803,31 +2803,13 @@ static void push_field(int fnum) #define STKP TT.stackp // pointer to top of stack -// Random number generator -// Extracted from http://www.cs.ucl.ac.uk/staff/d.jones/GoodPracticeRNG.pdf -// modified to encapsulate state and add seed function. -static struct jkiss32_state { - unsigned x, y, z, w, c, seed; -} jkst = {123456789, 234567891, 345678912, 456789123, 0, 1}; - -static unsigned jkiss32(void) -{ - int t; - jkst.y ^= (jkst.y<<5); jkst.y ^= (jkst.y>>7); jkst.y ^= (jkst.y<<22); - t = jkst.z+jkst.w+jkst.c; jkst.z = jkst.w; jkst.c = t<0; jkst.w = t&2147483647; - jkst.x += 1411392427; - return jkst.x + jkst.y + jkst.w; -} - -static unsigned seed_jkiss32(unsigned n) +static double seedrand(double seed) { - unsigned r = jkst.seed; - if (!n) n = 1; - jkst = (struct jkiss32_state){n*123456789, n*234567891, n*345678912, n*456789123, 0, n}; - if (n > 1) for (n = 10000; n--;) jkiss32(); + static double prev_seed; + double r = prev_seed; + srandom(trunc(prev_seed = seed)); return r; } -// END Random number generator static int popnumval(void) { @@ -3565,17 +3547,15 @@ static void math_builtin(int opcode, int nargs) break; case tkrand: push_int_val(0); - // STKP->num = rand(); // Not good in most libc implementations - // STKP->num = (double)jkiss32() / 4294967296.0; - // The above doesn't get all 53 mantissa bits in play. This does: + // Get all 53 mantissa bits in play: // (upper 26 bits * 2^27 + upper 27 bits) / 2^53 - double a = (jkiss32() >> 6) * 134217728.0; - STKP->num = (a + (jkiss32() >> 5)) / 9007199254740992.0; + STKP->num = + ((random() >> 5) * 134217728.0 + (random() >> 4)) / 9007199254740992.0; break; case tksrand: if (nargs == 1) { - STKP->num = seed_jkiss32((unsigned)trunc(val_to_num(STKP))); - } else push_int_val(seed_jkiss32((unsigned)millinow())); + STKP->num = seedrand(val_to_num(STKP)); + } else push_int_val(seedrand(millinow())); break; default: if (tkcos <= opcode && opcode <= tksqrt) { @@ -4456,7 +4436,7 @@ static void run(int optind, int argc, char **argv, char *sepstring, new_file("/dev/stdout", stdout, 'w', 'f')->is_std_file = 1; TT.zstdout = TT.zfiles; new_file("/dev/stderr", stderr, 'w', 'f')->is_std_file = 1; - seed_jkiss32(123); + seedrand(123); int status = -1, r = 0; if (TT.cgl.first_begin) r = interp(TT.cgl.first_begin, &status); if (r != tkexit) -- 2.39.2