The miracle is that if we mix the output of an LFSR and the output of an LCG, it passes ALL statistical tests : even PractRand. And mathematically we know that it will give 2^64 random bits.
First a 8-bytes seed must be put at seed:
The seed can vary from 0 to $FFFFFFFFFFFFFFFF.
And a 8-bytes seed must be put at seedlfsr:
The seed can vary from 1 to $FFFFFFFFFFFFFFFF but never 0 otherwise the LFSR produces only bits to 0.
Each call to the begin: function returns a pseudorandom byte in rndbyte:
First init: must be call one time.
After begin: must be call for each generated byte (rndbyte:) that can be use directly.
The test vector is :
For a seedlfsr = $FFFFFFFFFFFFFFFF
adn seed = $FFFFFFFFFFFFFFFF
the first 50 bytes are :
Code: Select all
// Pukall LFSR 64 + Pukall LCG 64
//----------------------------------------------------
// Main Program
//----------------------------------------------------
init:
jsr initlfsr
jsr initlcg
rts
begin:
jsr startlfsr
jsr beginlcg
lda rndbytelfsr
clc
adc rndbyte
sta rndbyte
rts
initlfsr:
ldx #0
looplfsr:
jsr startlfsr
inx
cpx #64
bne looplfsr
rts
startlfsr:
lda #$00
sta rndbytelfsr
lda #$01
sta mask
beginlfsr:
asl seedlfsr
rol seedlfsr+1
rol seedlfsr+2
rol seedlfsr+3
rol seedlfsr+4
rol seedlfsr+5
rol seedlfsr+6
rol seedlfsr+7
bcc notlfsr
lda seedlfsr
eor #$01
sta seedlfsr
lda seedlfsr+7
eor #$B0
sta seedlfsr+7
lda rndbytelfsr
ora mask
sta rndbytelfsr
notlfsr:
asl mask
bcc beginlfsr
rts
initlcg:
lda #6
sta pos
rts
beginlcg:
ldx pos
cpx #6
bne rnd
jsr start
ldx #0
clc
php
loop0:
lda seed,x
plp
adc dda,x
php
sta seed,x
inx
cpx #8
bne loop0
plp
rnd:
ldx pos
lda seed,x
sta rndbyte
dex
cpx #2
bne end2
end:
lda #6
sta pos
rts
end2:
stx pos
rts
start:
lda #0
ldx #15
loop:
sta result,x
dex
cpx #7
bne loop
ldy #64
part1:
sty storey
ldx #7
lsr seed,x
php
dex
loop1:
plp
ror seed,x
php
dex
cpx #0
bne loop1
plp
ror seed
bcc part2
ldx #7
ldy #0
clc
php
loop2:
inx
lda result,x
plp
adc two,y
php
sta result,x
iny
cpy #8
bne loop2
plp
part2:
ror
php
ldx #15
sta result,x
loop3:
dex
plp
ror result,x
php
cpx #0
bne loop3
plp
ldy storey
dey
bne jump
ldx #0
loop4:
lda result,x
sta seed,x
inx
cpx #8
bne loop4
rts
jump:
jmp part1
seed: .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
rndbyte: .byte $FF
result: .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
two: .byte $2D,$7F,$95,$4C,$2D,$F4,$51,$58
dda: .byte $01,$00,$00,$00,$00,$00,$00,$00
storey: .byte $FF
pos: .byte $FF
seedlfsr: .byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
mask: .byte $00
rndbytelfsr: .byte $00
Code: Select all
RNG_test using PractRand version 0.94
RNG = RNG_stdin8, seed = unknown
test set = core, folding = standard (8 bit)
rng=RNG_stdin8, seed=unknown
length= 8 megabytes (2^23 bytes), time= 3.7 seconds
no anomalies in 76 test result(s)
rng=RNG_stdin8, seed=unknown
length= 16 megabytes (2^24 bytes), time= 8.4 seconds
no anomalies in 84 test result(s)
rng=RNG_stdin8, seed=unknown
length= 32 megabytes (2^25 bytes), time= 17.0 seconds
no anomalies in 93 test result(s)
rng=RNG_stdin8, seed=unknown
length= 64 megabytes (2^26 bytes), time= 32.5 seconds
no anomalies in 99 test result(s)
rng=RNG_stdin8, seed=unknown
length= 128 megabytes (2^27 bytes), time= 62.7 seconds
no anomalies in 108 test result(s)
rng=RNG_stdin8, seed=unknown
length= 256 megabytes (2^28 bytes), time= 121 seconds
no anomalies in 118 test result(s)
rng=RNG_stdin8, seed=unknown
length= 512 megabytes (2^29 bytes), time= 237 seconds
no anomalies in 126 test result(s)
rng=RNG_stdin8, seed=unknown
length= 1 gigabyte (2^30 bytes), time= 470 seconds
no anomalies in 135 test result(s)
rng=RNG_stdin8, seed=unknown
length= 2 gigabytes (2^31 bytes), time= 936 seconds
no anomalies in 144 test result(s)
rng=RNG_stdin8, seed=unknown
length= 4 gigabytes (2^32 bytes), time= 1846 seconds
no anomalies in 151 test result(s)
rng=RNG_stdin8, seed=unknown
length= 8 gigabytes (2^33 bytes), time= 3662 seconds
no anomalies in 159 test result(s)
rng=RNG_stdin8, seed=unknown
length= 16 gigabytes (2^34 bytes), time= 7278 seconds
no anomalies in 167 test result(s)
rng=RNG_stdin8, seed=unknown
length= 32 gigabytes (2^35 bytes), time= 14372 seconds
no anomalies in 173 test result(s)
rng=RNG_stdin8, seed=unknown
length= 64 gigabytes (2^36 bytes), time= 28416 seconds
no anomalies in 181 test result(s)
rng=RNG_stdin8, seed=unknown
length= 128 gigabytes (2^37 bytes), time= 55896 seconds
no anomalies in 189 test result(s)
rng=RNG_stdin8, seed=unknown
length= 256 gigabytes (2^38 bytes), time= 110189 seconds
no anomalies in 195 test result(s)
rng=RNG_stdin8, seed=unknown
length= 512 gigabytes (2^39 bytes), time= 208856 seconds
no anomalies in 202 test result(s)
rng=RNG_stdin8, seed=unknown
length= 1 terabyte (2^40 bytes), time= 369656 seconds
no anomalies in 208 test result(s)
rng=RNG_stdin8, seed=unknown
length= 2 terabytes (2^41 bytes), time= 686317 seconds
no anomalies in 213 test result(s)