fork download
  1. # Ranlux 24/48 PRNGs. (1.01)
  2. # Chaotic with long period but slow (due to discard).
  3.  
  4. from collections import deque
  5. from random import choices
  6.  
  7. class SubtractWithCarryEngine:
  8. def __init__(self, w, s, r):
  9. assert 0 < w
  10. assert 0 < s < r
  11. self.m = 2**w-1
  12. self.s = s
  13. self.r = r
  14. self.x = deque(choices(range(2**w), k=r), maxlen=r)
  15. self.c = 0
  16.  
  17. def next(self):
  18. x = self.x
  19. i = len(x)
  20. y = x[i - self.s] - x[i - self.r] - self.c
  21. self.c = 1 if y < 0 else 0
  22. x.append(y & self.m)
  23. return x[-1]
  24.  
  25. def discard(self, n):
  26. for _ in range(n):
  27. self.next()
  28.  
  29. class DiscardBlockEngine:
  30. def __init__(self, g, p, r):
  31. assert 0 < r <= p
  32. self.g = g
  33. self.p = p
  34. self.r = r
  35. self.n = r
  36.  
  37. def next(self):
  38. if self.n == 0:
  39. self.g.discard(self.p - self.r)
  40. self.n = self.r
  41. self.n -= 1
  42. return self.g.next()
  43.  
  44. # Test.
  45.  
  46. def bitstream(n, prng, bits, *, end='\n', file=None):
  47. assert bits > 0
  48. while n > 0:
  49. m = min(n, bits)
  50. n -= m
  51. r = prng.next()
  52. for i in reversed(range(bits - m, bits)):
  53. print(chr(((r >> i) & 1) + ord('0')), end='', file=file)
  54. print(end=end, file=file)
  55.  
  56. ranlux24_base = SubtractWithCarryEngine(24, 10, 24)
  57. ranlux24 = DiscardBlockEngine(ranlux24_base, 223, 23)
  58. ranlux48_base = SubtractWithCarryEngine(48, 5, 12)
  59. ranlux48 = DiscardBlockEngine(ranlux48_base, 389, 11)
  60.  
  61. n = 50
  62. bitstream(n, ranlux24, 24)
  63. bitstream(n, ranlux48, 48)
  64.  
  65. print('Ranlux24:')
  66. for i in range(24):
  67. print(' ', ranlux24.next())
  68. print('Ranlux48:')
  69. for i in range(12):
  70. print(' ', ranlux48.next())
Success #stdin #stdout 0.03s 10008KB
stdin
Standard input is empty
stdout
01100001000110001101010101100010011111111011110000
10001000000110001110111101011000101110011110000001
Ranlux24:
  9379209
  7504306
  771354
  9085551
  10478996
  5356231
  9838116
  12569044
  6365017
  4474206
  1197765
  12661067
  16751339
  10690517
  11500033
  2501708
  10075546
  6033768
  7393416
  13565427
  7301592
  7855867
  6284543
  1521765
Ranlux48:
  213763982943830
  118202110845876
  121276332706400
  272850298363850
  128279167574529
  280154039702278
  166530945232229
  187918905056227
  101350856956577
  237492062835607
  127860856501848
  116381012032562