Added uniqueness check to rnd number seed generator

* some seeds were being marked as valid when they had repeating patterns
This commit is contained in:
Rob McMullen 2017-08-29 09:03:02 -07:00
parent e377daf598
commit 2f0a592d58

View File

@ -1,113 +1,46 @@
#!/usr/bin/env python
import numpy as np
# prng16:
# lsr rand+1
# ror rand
# bcc skip
# lda rand+1
# ; $60 = 1..32767, see table above
# eor #$60
# sta rand+1
# skip:
# rts
# rand:
# ; seed mustn't be zero!
# .byte $01,$00
# lfsr_order = [
# (0x03, 0x03, ),
# (0x07, 0x06, ),
# (0x0f, 0x0c, ),
# (0x1f, 0x14, ),
# (0x3f, 0x30, ),
# (0x7f, 0x60, ),
# (0xff, 0xb8, ),
# ]
# def get_prng(framenum):
# if framenum < 0 or framenum > 6:
# return []
# seed = 0x843f
# period, term = lfsr_order[framenum]
# order = []
# seed = (seed & period) | 0x01
# for i in range(period):
# rand = seed >> 1
# if seed & 0x01:
# rand ^= term
# #order.append((rand & period) - 1 - period // 2 + 96)
# #print("%d seed=%x rand=%x &period=%x" % (i, seed, rand, rand & period))
# order.append((rand & period))
# seed = rand
# return order
# adc/xor routine from:
# https://stackoverflow.com/questions/17411712/finding-seeds-for-a-5-byte-prng
adcxor_order = [
(3, 0x07, 0x3, 0x7),
(4, 0x0f, 0x7, 0xd),
(5, 0x1f, 0x9, 0x1f),
(6, 0x3f, 0x7, 0x17),
(7, 0x7f, 0x15, 0x5b),
(8, 0xff, 0x3b, 0x3f),
]
def get_prng(framenum):
if framenum < 0 or framenum > 5:
return []
BITS, period, num1, num2 = adcxor_order[framenum]
order = []
r = 0
for i in range(period):
r=(((r>>(BITS-1)) & 1)+r+r+num1)^num2
r&=(1<<(BITS-1)) | ((1<<(BITS-1))-1)
order.append(r)
return order
# Pretty good choices for 8 bit seeds
adcxor_8bit = [
(0x03, 0x045),
(0x03, 0x073),
(0x03, 0x085),
(0x03, 0x0b3),
(0x0d, 0x04d),
(0x0d, 0x08d),
(0x23, 0x033),
(0x23, 0x0f3),
(0x3b, 0x03f),
(0x3b, 0x0ff),
(0x45, 0x07f),
(0x45, 0x0bf),
(0x5d, 0x073),
(0x5d, 0x0b3),
(0x73, 0x00d),
(0x73, 0x0cd),
(0x7d, 0x005),
(0x7d, 0x033),
(0x7d, 0x0c5),
(0x7d, 0x0f3),
]
(0x03, 0x045),
(0x03, 0x073),
(0x03, 0x085),
(0x03, 0x0b3),
(0x0d, 0x04d),
(0x0d, 0x08d),
(0x23, 0x033),
(0x23, 0x0f3),
(0x3b, 0x03f),
(0x3b, 0x0ff),
(0x45, 0x07f),
(0x45, 0x0bf),
(0x5d, 0x073),
(0x5d, 0x0b3),
(0x73, 0x00d),
(0x73, 0x0cd),
(0x7d, 0x005),
(0x7d, 0x033),
(0x7d, 0x0c5),
(0x7d, 0x0f3),
]
def get_prng8(framenum):
num1, num2 = adcxor_8bit[framenum]
def get_prng8(bits, adc, xor):
order = []
r = 0
BITS = 8
for i in range(255):
r=(((r>>(BITS-1)) & 1)+r+r+num1)^num2
r&=(1<<(BITS-1)) | ((1<<(BITS-1))-1)
for i in range(2**bits):
r=(((r>>(bits-1)) & 1)+r+r+adc)^xor
r&=(1<<(bits-1)) | ((1<<(bits-1))-1)
order.append(r)
return order
if __name__ == '__main__':
gen_16_bit = False
summary = False
summary = True
show = True
if gen_16_bit:
random_bits = 16
@ -115,39 +48,44 @@ if __name__ == '__main__':
random_bits = 8
valid_seeds = []
mc = 0
for BITS in range(2, random_bits + 1):
mc = 0
num1 = 1
adc = 1 # Only odd add values produce useful results
while True:
num2 = 1
xor = 1 # Only odd add values produce useful results
while True:
r = 0
c = 0
c = ~0
values = []
while True:
r=(((r>>(BITS-1)) & 1)+r+r+num1)^num2
r=(((r>>(BITS-1)) & 1)+r+r+adc)^xor
r&=(1<<(BITS-1)) | ((1<<(BITS-1))-1)
c += 1
values.append(r)
if r == 0:
break
if c == (1 << BITS):
#print("BITS: %d Num1(adc): %04x, Num2(eor): %04x count=%d values=%s" % (BITS, num1, num2, len(values), ",".join("%x" % x for x in values)))
valid_seeds.append((BITS, num1, num2))
print("BITS: %d Num1(adc): %04x, Num2(eor): %04x" % (BITS, num1, num2))
# if c >= mc:
# mc = c
# print("BITS: %x Count-1: %04x, Num1(adc): %04x, Num2(eor): %04x\n" % (BITS, c, num1, num2))
num2 += 2
num2 &= (1<<(BITS-1)) | ((1<<(BITS-1))-1)
if num2 == 1:
if c >= mc:
mc = c
valid_seeds.append((BITS, adc, xor))
if not summary:
print("BITS: %d adc: %04x, xor: %04x" % (BITS, adc, xor))
xor += 2
xor &= (1<<(BITS-1)) | ((1<<(BITS-1))-1)
if xor == 1:
break
num1 += 2
num1 &= ((1<<(BITS-1))-1) # * Do not check complements
if num1 == 1:
adc += 2
adc &= ((1<<(BITS-1))-1) # * Do not check complements
if adc == 1:
break
if summary:
for bits, num1, num2 in valid_seeds:
print("BITS: %d Num1(adc): %04x, Num2(eor): %04x" % (bits, num1, num2))
for bits, adc, xor in valid_seeds:
print("BITS: %d adc(adc): %04x, xor(eor): %04x" % (bits, adc, xor))
if show:
values = get_prng8(bits, adc, xor)
unique_check = set(values)
if len(values) == len(unique_check):
print("%d: %s" % (len(values), str(values)))
else:
print("Failed unique check")