nntrac

No-nonsense TRAC T-64 reimplementation under 1000 SLOC of ANSI C
git clone git://git.luxferre.top/nntrac.git
Log | Files | Refs | README | LICENSE

commit 9acabe0de87eef95c2b54accc7a493a21b359da4
parent 5bd1524917a0589ef1a89ceb4d69df42f2d40f59
Author: Luxferre <lux@ferre>
Date:   Thu, 10 Aug 2023 09:11:43 +0300

improved prng

Diffstat:
MREADME.md | 2+-
Mnntrac.c | 12+++++++-----
2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md @@ -85,7 +85,7 @@ Name|Args|Implemented?|UTF-8 safe?|Meaning - `sf`: store (raw) file. 3 arguments: `#(sf,fname,form)`. Stores the raw value from `form` into a named file. The value is always written in its entirety (the form pointer is ignored) and segment gap bytes, if there are any, are written "as is". Returns a null value. The form doesn't get deleted from the internal form storage. The file is fully overwritten if it already exists. - `ff`: fetch (raw) file. 3 arguments: `#(ff,fname,form)`. Reads a raw string from the named file into `form`. Returns null value (check the target form afterwards). - `tm`: local/UTC/Epoch time. 2 or 3 arguments: `#(tl,fmt[,U])`. Returns the local (or UTC, if the third parameter `U` is specified) time formatted according to the strftime-compatible `fmt` string or `E` format. If the format string is just `E` (Epoch), returns the amount of seconds since 00:00:00 UTC, January 1, 1970. -- `rn`: random number. 3 arguments: `#(rn,n1,n2)`. Returns a (pseudo-)random integer number in the range `n1` (included) to `n2` (not included). Implemented using the xorshift64 algorithm. +- `rn`: random number. 3 arguments: `#(rn,n1,n2)`. Returns a (pseudo-)random integer number in the range `n1` (included) to `n2` (not included). Implemented using the double-pass xorshift64* algorithm. - `os`: run an OS command. 2 arguments: `#(os,cmd)`. Runs a command in the external OS shell (the one determined by the `system()` C call) and returns the command exit code. The output is not captured. For self-contained nntrac environments that have no external shell (or the shell is nntrac itself), you can disable the `os` primitive by building nntrac with the `-DNNT_NO_EXTSHELL` flag. diff --git a/nntrac.c b/nntrac.c @@ -1061,9 +1061,11 @@ char *prim_tm(char *arglist, char *res, int *reslen) { } static unsigned long long nnt_rngs; /* PRNG state*/ -unsigned long long xorshift64() { - nnt_rngs^=(nnt_rngs<<13);nnt_rngs^=(nnt_rngs>>7);nnt_rngs^=(nnt_rngs<<17); - return nnt_rngs; +unsigned long long xorshift64s() { + nnt_rngs^=(nnt_rngs>>12);nnt_rngs^=(nnt_rngs<<25);nnt_rngs^=(nnt_rngs>>27); + unsigned long long inter = (nnt_rngs * 0x2545F4914F6CDD1DULL) >> 32; + nnt_rngs^=(nnt_rngs>>12);nnt_rngs^=(nnt_rngs<<25);nnt_rngs^=(nnt_rngs>>27); + return (inter << 32) | ((nnt_rngs * 0x2545F4914F6CDD1DULL) & 0xFFFFFFFF); } /* [new] rn primitive: (pseudo)random number */ @@ -1073,7 +1075,7 @@ char *prim_rn(char *arglist, char *res, int *reslen) { *tos = strtok(NULL, NNT_ADEL_S); long long a = (froms == NULL) ? 0 : snum(froms), b = (tos == NULL) ? ARITH_LIMIT : snum(tos); - res = n2s(a == b ? a : (a + xorshift64() % (b - a)), res, reslen); + res = n2s(a == b ? a : (a + xorshift64s() % (b - a)), res, reslen); return res; } @@ -1081,7 +1083,7 @@ char *prim_rn(char *arglist, char *res, int *reslen) { void nnt_init() { nnt_forms = malloc(0); /* init the forms table */ nnt_primitives = malloc(0); /* init the primitives table */ - nnt_rngs = time(NULL); xorshift64(); /* init the PRNG */ + nnt_rngs = time(NULL); xorshift64s(); /* init the PRNG */ nnt_regprimitive("ps", &prim_ps); nnt_regprimitive("rc", &prim_rc); nnt_regprimitive("rs", &prim_rs);