stdlib/rand: replace weak LCG with xorshift32 PRNG#19244
Merged
Conversation
|
xiaoxiang781216
approved these changes
Jul 1, 2026
Contributor
|
@Zepp-Hanzj flash is too small: |
Contributor
This seems like a mainline issue, happens across all new merge requests. |
acassis
approved these changes
Jul 1, 2026
The existing first-order LCG (seed = 470001 * seed % 999563) has several quality problems: - Output range limited to [1, 999562] (~20 bits) instead of full 32-bit - Lower bits have very short periods (8-bit period = 1, 16-bit = 105) - Overall period only ~1M, far too short for many applications - Causes mbedtls_rsa_gen_key to loop forever when rand() consumption aligns with the cycle length (issue apache#16760) Replace the entire order-based LCG implementation (CONFIG_LIBC_RAND_ORDER 0-3) with Marsaglia's xorshift32: - Full 32-bit output range - Period 2^32 - 1 (~4.29 billion) - Fast: just three XOR/shift operations - No floating-point math needed - No CONFIG_LIBC_RAND_ORDER configuration required Remove the CONFIG_LIBC_RAND_ORDER Kconfig option and clean up all defconfig references (12 boards) and related comments. Signed-off-by: hanzhijian <hanzhijian@zepp.com>
a68e799 to
77519b1
Compare
Contributor
|
@Zepp-Hanzj please fix: |
77519b1 to
af7e040
Compare
Contributor
Author
|
@xiaoxiang781216 Sorry for the noise. The two empty "ci: retrigger build" commits were added to retrigger CI after the stm32l0538-disco flash overflow issue was resolved on upstream master. They have been removed now — the PR contains only the single actual change commit. CI should pass cleanly this time. |
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The existing first-order LCG (seed = 470001 * seed % 999563) has several quality problems:
Replace the entire order-based LCG implementation (CONFIG_LIBC_RAND_ORDER 0-3) with Marsaglia's xorshift32:
Remove the CONFIG_LIBC_RAND_ORDER Kconfig option and clean up all defconfig references (12 boards) and related comments.
Verification
Built and tested on sim:nsh. Replaced hello_main.c with a test program that checks rand() quality, then restored it after testing.
Build command:
make distclean
tools/configure.sh sim:nsh
make -j$(nproc)
Run command:
printf 'hello\npoweroff\n' | timeout 30 ./nuttx 2>/dev/null
Test output (3 consecutive runs, all identical as expected for deterministic PRNG with same seed):
NuttShell (NSH) NuttX-13.0.0-RC0
nsh> hello
=== rand() quality test ===
Range after 10000 calls: [84907, 2147393180]
Expected: [0, 2147483647]
Full value repeat within 500k: NOT FOUND (period=0)
Expected: NOT FOUND (period should be ~4 billion)
srand(0) first call: 270369 (should be non-zero)
nrand(100) = 89 (should be 0-99)
=== test complete ===
nsh> poweroff
What each check means:
Range [84907, 2147393180] — max value close to INT_MAX (2147483647), old LCG only reached ~999562
Full value repeat: NOT FOUND — no repeat within 500k calls, old LCG repeated within ~1M
srand(0) non-zero — zero seed does not degenerate the generator
nrand(100) in [0,99] — range mapping works correctly
Also confirmed via nm that the NuttX xorshift32 is linked into the binary (not host GLIBC):
$ nm nuttx | grep xorshift32
000000004019d160 b __gcov0.xorshift32
00000000401740a0 d _gcov.xorshift32
00000000400c4052 t xorshift32