Post by dxforthDon't C compilers already come with reasonable RNGs?
Well... an old draft of the C11 standard I saw linked on Wikipedia [1]
had this memorable footnote regarding rand():
"There are no guarantees as to the quality of the random sequence
produced and some implementations are known to produce sequences with
distressingly non-random low-order bits."
I remember noticing that myself in the 90s, so I expect it was fairly
common knowledge even then.
Anyway, I believe Hitech C (presumably most relevant here) uses what I
think is the old ANSI C example implementation - though the routine
seems to date back at least as far as V7 in 1979 - multiply by
1103515245, add 12345, and return bits 30-16. From a quick look I
think lcg16of32_extended in PractRand does something very similar,
with results like this when tested:
***@wedge:1938:/home/rus>RNG_test lcg16of32_extended
RNG_test using PractRand version 0.95
RNG = lcg16of32_extended, seed = 0xf050291b
test set = core, folding = standard (16 bit)
rng=lcg16of32_extended, seed=0xf050291b
length= 64 megabytes (2^26 bytes), time= 3.2 seconds
Test Name Raw Processed Evaluation
TMFn(2+0):wl R=+258.3 p~= 2e-148 FAIL !!!!!
TMFn(2+1):wl R=+127.4 p~= 1e-69 FAIL !!!!
[Low4/16]DC6-9x1Bytes-1 R=+109.1 p = 7.3e-63 FAIL !!!!
[Low4/16]Gap-16:A R=+220.2 p = 4.0e-173 FAIL !!!!!!
[Low4/16]Gap-16:B R=+348.2 p = 1.6e-314 FAIL !!!!!!
[Low4/16]FPF-14+6/16:all R= -7.0 p =1-1.9e-6 suspicious
[Low1/16]BCFN(2+0,13-6,T) R= +83.5 p = 5.1e-29 FAIL !!!
[Low1/16]BCFN(2+1,13-6,T) R=+132.0 p = 1.2e-45 FAIL !!!
[Low1/16]BCFN(2+2,13-6,T) R=+151.7 p = 2.2e-52 FAIL !!!!
[Low1/16]BCFN(2+3,13-6,T) R= +72.7 p = 2.5e-25 FAIL !!
[Low1/16]BCFN(2+4,13-7,T) R= +78.5 p = 3.0e-24 FAIL !!
[Low1/16]BCFN(2+5,13-8,T) R= +73.8 p = 1.1e-19 FAIL !
[Low1/16]BCFN(2+6,13-8,T) R= +42.0 p = 1.3e-11 VERY SUSPICIOUS
[Low1/16]DC6-9x1Bytes-1 R=+898.4 p = 3.1e-506 FAIL !!!!!!!
[Low1/16]Gap-16:A R= +1948 p = 2e-1567 FAIL !!!!!!!!
[Low1/16]Gap-16:B R= +2300 p = 3e-1735 FAIL !!!!!!!!
[Low1/16]FPF-14+6/16:(0,14-2) R= +78.6 p = 1.6e-68 FAIL !!!!
[Low1/16]FPF-14+6/16:(1,14-3) R= +54.8 p = 8.6e-48 FAIL !!!
[Low1/16]FPF-14+6/16:(2,14-4) R= +33.2 p = 4.4e-27 FAIL !!
[Low1/16]FPF-14+6/16:(3,14-5) R= +22.9 p = 8.3e-19 FAIL !
[Low1/16]FPF-14+6/16:(4,14-5) R= +41.5 p = 3.0e-34 FAIL !!!
[Low1/16]FPF-14+6/16:(5,14-6) R= +23.9 p = 2.3e-18 FAIL !
[Low1/16]FPF-14+6/16:(6,14-7) R= +15.3 p = 5.0e-12 VERY SUSPICIOUS
[Low1/16]FPF-14+6/16:(7,14-8) R= +17.9 p = 6.2e-13 VERY SUSPICIOUS
[Low1/16]FPF-14+6/16:(8,14-8) R= +12.3 p = 6.5e-9 very suspicious
[Low1/16]FPF-14+6/16:(9,14-9) R= +9.0 p = 5.6e-6 unusual
[Low1/16]FPF-14+6/16:(10,14-10) R= +18.1 p = 3.2e-10 very suspicious
[Low1/16]FPF-14+6/16:all R=+117.2 p = 3.6e-105 FAIL !!!!!
...and 118 test result(s) without anomalies
Perhaps it's better than a plain xorshift in some ways - I doubt I'm
the best person to make that call. But it does seem to have flaws of
its own. :-)
-Rus.
[1] From here, an interesting page in itself not least for the list of
"Parameters in common use", and I can only applaud any list which
sees fit to include the Sinclair ZX81 in that context:
https://en.wikipedia.org/wiki/Linear_congruential_generator