From 91dc415675965fd753fdf2e99d56dff04bd92fc1 Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Wed, 17 Jun 2026 13:48:05 +0000 Subject: [PATCH] 0718 nwnss: provide stdlib random wrappers --- nwnss-audit.md | 4 +-- src/nwnss/library/misc/rand.c | 48 +++++++++++++++++++++++++++ tests/nwnss/rand/test_nwnss_rand.c | 52 ++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 2 deletions(-) diff --git a/nwnss-audit.md b/nwnss-audit.md index db4be1d..d10a466 100644 --- a/nwnss-audit.md +++ b/nwnss-audit.md @@ -116,7 +116,7 @@ still stay original and remain listed, because later imports may rely on them. | AUDITED | `src/nwnss/library/bit.c` | PORT | nwnss.bit, nwnss.bitmap | No original provider found beyond bit.h/libNSS.imp; native-NINT semantics fixed/tested in 0698. | | AUDITED | `src/nwnss/library/que.c` + `src/nwnss/sharedsrc/que.c.h` + `include/nwnss/library/que.h` | ORIG wrapper + ORIG+FIX sharedsrc/header | nwnss.que | Wrapper matches Novell sharedsrc pattern; header and sharedsrc compared with original. Abweichungen sind Include-Pfad-Fixes, legacy callback casts and whitespace/diff-check cleanup only; STK/SQ/CIR/DQ/SET semantics tested in 0706. | | AUDITED | `src/nwnss/library/qdiv.c` | ORIG+FIX | nwnss.qdiv | Compared with original `public_core/library/qdiv.c`; Knuth/Berkeley quad division implementation kept, with signed helper prototypes adjusted from `QUAD` to `SQUAD` because Mars `QUAD` is unsigned. Unsigned, signed, null-remainder and fuzz cases tested in 0707. | -| AUDITED | `src/nwnss/library/misc/rand.c` | PORT | nwnss.rand, nwnss.namespace | No original provider found beyond rand.h/libNSS.imp/callers; seed-deterministic PRNG port checked in 0700/0701; libsodium only initializes default state before explicit seeding. | +| AUDITED | `src/nwnss/library/misc/rand.c` | PORT | nwnss.rand, nwnss.namespace | No original provider found beyond rand.h/libNSS.imp/callers; seed-deterministic PRNG port checked in 0700/0701/0718; also provides xStdlib.h rand/random/srand/srandom/initstate/setstate wrappers; libsodium only initializes default state before explicit seeding. | | AUDITED | `src/nwnss/library/misc/rbpTree.c` | PORT | nwnss.rbpTree | No original provider found beyond rbpTree.h/libNSS.imp/callers; CLRS-style algorithmic port checked against header contract in 0703 and strengthened in 0705 with explicit red/black, parent-link, binary-search-order, black-height, and Coin3D-style insertion/deletion stress coverage. Coin3D rbptree.cpp was checked only as an external BSD-licensed CLRS comparison and was not imported. | | TODO | `src/nwnss/library/os/currentTime.c` | PORT | nwnss.utc | Userspace time port; full audit open. | | AUDITED | `src/nwnss/library/os/delay.c` | ORIG+FIX/PORT | nwnss.schedule, nwnss.snooze | Scheduler functions kept as functions, not macros; checked in 0688-0690. | @@ -616,7 +616,7 @@ even if it already compiles or has indirect test coverage. | TODO | ORIG+FIX? | not yet classified | `src/nwnss/library/misc/histogram.c` | Must be compared against original source and classified. | | TODO | ORIG+FIX? | not yet classified | `src/nwnss/library/misc/lbVolume.c` | Must be compared against original source and classified. | | TODO | ORIG+FIX? | not yet classified | `src/nwnss/library/misc/nssErrorTable.c` | Must be compared against original source and classified. | -| AUDITED | PORT | nwnss.rand, nwnss.namespace | `src/nwnss/library/misc/rand.c` | No original provider found beyond rand.h/libNSS.imp/callers; seed-deterministic PRNG port checked in 0700/0701; libsodium only initializes default state before explicit seeding. | +| AUDITED | PORT | nwnss.rand, nwnss.namespace | `src/nwnss/library/misc/rand.c` | No original provider found beyond rand.h/libNSS.imp/callers; seed-deterministic PRNG port checked in 0700/0701/0718; also provides xStdlib.h rand/random/srand/srandom/initstate/setstate wrappers; libsodium only initializes default state before explicit seeding. | | AUDITED | PORT | nwnss.rbpTree | `src/nwnss/library/misc/rbpTree.c` | No original provider found beyond rbpTree.h/libNSS.imp/callers; CLRS-style algorithmic port checked against header contract in 0703 and strengthened in 0705 with explicit red/black, parent-link, binary-search-order, black-height, and Coin3D-style insertion/deletion stress coverage. Coin3D rbptree.cpp was checked only as an external BSD-licensed CLRS comparison and was not imported. | | TODO | ORIG+FIX? | not yet classified | `src/nwnss/library/misc/register.c` | Must be compared against original source and classified. | | TODO | ORIG+FIX? | not yet classified | `src/nwnss/library/misc/sysimp.c` | Must be compared against original source and classified. | diff --git a/src/nwnss/library/misc/rand.c b/src/nwnss/library/misc/rand.c index 6702df0..abff8cc 100644 --- a/src/nwnss/library/misc/rand.c +++ b/src/nwnss/library/misc/rand.c @@ -90,6 +90,54 @@ QUAD rndLong(void) return (QUAD)randQuad(); } +int LB_rand(void) +{ + return (int)(randQuad() & 0x7fffU); +} + +void LB_srand(unsigned int seed) +{ + srandQuad((QUAD)seed); +} + +long LB_random(void) +{ + return (long)(randQuad() & 0x7fffffffUL); +} + +void LB_srandom(unsigned int seed) +{ + srandQuad((QUAD)seed); +} + +char *LB_setstate(char *arg_state) +{ + QUAD seed = 0; + unsigned i; + + if (arg_state == 0) + return 0; + + for (i = 0; i < sizeof(seed); ++i) + seed |= ((QUAD)(unsigned char)arg_state[i]) << (i * 8); + + srandQuad(seed); + return arg_state; +} + +char *LB_initstate(unsigned int seed, char *arg_state, int n) +{ + unsigned i; + + if (arg_state == 0 || n < (int)sizeof(QUAD)) + return 0; + + for (i = 0; i < sizeof(QUAD); ++i) + arg_state[i] = (char)(((QUAD)seed >> (i * 8)) & 0xffU); + + LB_srandom(seed); + return arg_state; +} double chiSquareQuad( unsigned numTests, diff --git a/tests/nwnss/rand/test_nwnss_rand.c b/tests/nwnss/rand/test_nwnss_rand.c index 5f95451..63c8c5d 100644 --- a/tests/nwnss/rand/test_nwnss_rand.c +++ b/tests/nwnss/rand/test_nwnss_rand.c @@ -1,4 +1,5 @@ #include +#include #include @@ -116,12 +117,63 @@ static int check_chi_square(void) return 0; } + +static int check_stdlib_rand_wrappers(void) +{ + int rand_a[3]; + int rand_b[3]; + long random_a[3]; + long random_b[3]; + char state[8]; + int i; + + LB_srand(1234U); + for (i = 0; i < 3; ++i) { + rand_a[i] = LB_rand(); + CHECK(rand_a[i] >= 0); + CHECK(rand_a[i] <= 0x7fff); + } + + LB_srand(1234U); + for (i = 0; i < 3; ++i) + rand_b[i] = LB_rand(); + + for (i = 0; i < 3; ++i) + CHECK(rand_a[i] == rand_b[i]); + CHECK(rand_a[0] != rand_a[1]); + + LB_srandom(0x9876U); + for (i = 0; i < 3; ++i) { + random_a[i] = LB_random(); + CHECK(random_a[i] >= 0); + CHECK(random_a[i] <= 0x7fffffffL); + } + + LB_srandom(0x9876U); + for (i = 0; i < 3; ++i) + random_b[i] = LB_random(); + + for (i = 0; i < 3; ++i) + CHECK(random_a[i] == random_b[i]); + + CHECK(LB_initstate(0x55aaU, state, (int)sizeof(state)) == state); + rand_a[0] = LB_rand(); + CHECK(LB_setstate(state) == state); + CHECK(LB_rand() == rand_a[0]); + CHECK(LB_initstate(1U, 0, (int)sizeof(state)) == 0); + CHECK(LB_initstate(1U, state, 0) == 0); + CHECK(LB_setstate(0) == 0); + + return 0; +} + int main(void) { CHECK(check_repeatable_quad_seed() == 0); CHECK(check_repeatable_rnd_quad_seed() == 0); CHECK(check_repeatable_long_seed() == 0); CHECK(check_chi_square() == 0); + CHECK(check_stdlib_rand_wrappers() == 0); return 0; }