ladislau szilagyi <
ladislau...@euroqst.ro> wrote:
> At last, it seems I have the perfect random numbers generator for Z80.
It looks fast at least. I presume it's based on this, or the
retroprogramming.com page it links to:
https://github.com/impomatic/xorshift798
Unfortunately I can't see any licence specified anywhere, which
seems troublesome. Perhaps an oversight.
> George Marsaglia's xorshift
Funnily enough, I did a Z80 version of a 32-bit xorshift from
"Xorshift RNGs" for my zcsoli game (arguably a silly choice, as it
only uses half of that).
Another RNG I like is Chris Doty-Humphrey's sfc_v3_16 from PractRand,
which seems to stand up surprisingly well to randomness testing while
still being fairly fast when converted to Z80 (though it's over twice
the size of the routine you posted, and significantly slower). His
original and my port are both public domain. I used it in ZCN 1.4's
cpmtris and zcnlib:
https://zgedneil.nfshost.com/zcn.html
Speaking of PractRand, I'll just go well overboard here :-) and show
how "RNG_test" from that assesses the randomness of sfc_v3_16 and
xorshift32 (which I would intuitively expect to give better results
than the 16-bit xorshift798, given the similar algorithm). This is
just one run each, but it gives you the idea I think:
rus@wedge:1001:/home/rus>RNG_test xorshift32
RNG_test using PractRand version 0.95
RNG = xorshift32, seed = 0x697d15c6
test set = core, folding = standard (32 bit)
rng=xorshift32, seed=0x697d15c6
length= 64 megabytes (2^26 bytes), time= 2.8 seconds
Test Name Raw Processed Evaluation
BCFN(2+0,13-3,T) R= +45.9 p = 1.5e-21 FAIL !!
BCFN(2+1,13-3,T) R= +8.4 p = 9.2e-4 unusual
DC6-9x1Bytes-1 R=+471.6 p = 3.8e-300 FAIL !!!!!!
BRank(12):128(4) R= +3922 p~= 8e-2087 FAIL !!!!!!!!
BRank(12):256(2) R= +6670 p~= 5e-2009 FAIL !!!!!!!!
BRank(12):384(1) R= +7472 p~= 2e-2250 FAIL !!!!!!!!
BRank(12):512(2) R=+14464 p~= 4e-4355 FAIL !!!!!!!!
BRank(12):768(1) R=+15738 p~= 8e-4739 FAIL !!!!!!!!
BRank(12):1K(1) R=+21249 p~= 9e-6398 FAIL !!!!!!!!
[Low8/32]BRank(12):128(4) R= +3922 p~= 8e-2087 FAIL !!!!!!!!
[Low8/32]BRank(12):256(2) R= +6670 p~= 5e-2009 FAIL !!!!!!!!
[Low8/32]BRank(12):384(1) R= +7472 p~= 2e-2250 FAIL !!!!!!!!
[Low8/32]BRank(12):512(2) R=+14464 p~= 4e-4355 FAIL !!!!!!!!
[Low8/32]BRank(12):768(1) R=+15738 p~= 8e-4739 FAIL !!!!!!!!
[Low1/32]BRank(12):128(2) R= +2773 p~= 6.9e-836 FAIL !!!!!!!
[Low1/32]BRank(12):256(2) R= +6670 p~= 5e-2009 FAIL !!!!!!!!
[Low1/32]BRank(12):384(1) R= +7472 p~= 2e-2250 FAIL !!!!!!!!
...and 125 test result(s) without anomalies
rus@wedge:1002:/home/rus>RNG_test sfc_v3_16
RNG_test using PractRand version 0.95
RNG = sfc_v3_16, seed = 0x9d9758a7
test set = core, folding = standard (16 bit)
rng=sfc_v3_16, seed=0x9d9758a7
length= 64 megabytes (2^26 bytes), time= 3.0 seconds
no anomalies in 146 test result(s)
rng=sfc_v3_16, seed=0x9d9758a7
length= 128 megabytes (2^27 bytes), time= 7.5 seconds
no anomalies in 159 test result(s)
rng=sfc_v3_16, seed=0x9d9758a7
length= 256 megabytes (2^28 bytes), time= 14.8 seconds
no anomalies in 172 test result(s)
rng=sfc_v3_16, seed=0x9d9758a7
length= 512 megabytes (2^29 bytes), time= 27.6 seconds
Test Name Raw Processed Evaluation
[Low4/16]FPF-14+6/16:all R= +5.1 p = 3.0e-4 unusual
...and 184 test result(s) without anomalies
rng=sfc_v3_16, seed=0x9d9758a7
length= 1 gigabyte (2^30 bytes), time= 52.0 seconds
no anomalies in 198 test result(s)
rng=sfc_v3_16, seed=0x9d9758a7
length= 2 gigabytes (2^31 bytes), time= 98.8 seconds
no anomalies in 210 test result(s)
rng=sfc_v3_16, seed=0x9d9758a7
length= 4 gigabytes (2^32 bytes), time= 190 seconds
no anomalies in 222 test result(s)
rng=sfc_v3_16, seed=0x9d9758a7
length= 8 gigabytes (2^33 bytes), time= 375 seconds
no anomalies in 233 test result(s)
[...and so on.]
So, while the routine being (in that Z80 port) slower and twice as big
is clearly an issue, at least according to PractRand itself that does
seem to buy you quite an improvement in the quality of the output.
Does this matter in a game? Maybe not. But I think it's worth noting.
> I wonder how many Z80 simulators/emulators will correctly execute
> the 'ld a,r' instruction ?
That should really be supported by any full Z80 emulation, so it's
unlikely to be a problem. It's an important one to emulate due to uses
like this, and because you can potentially use the top bit to store
data. And it even gives you a way of checking whether interrupts were
previously enabled or not in e.g. an NMI handler.
-Rus.