fork(1) download
  1. # Ranlux 24/48 PRNGs
  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)
  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.04s 10012KB
stdin
Standard input is empty
stdout
01111101100010011000101110110101001001100010001101
01100101100001100001000001100101011001001110100101
Ranlux24:
  12995816
  15286171
  12349675
  12402482
  11968225
  14621338
  6796619
  6914732
  12028705
  5275685
  10746843
  7883456
  564732
  16384640
  16175414
  571636
  1339995
  15669122
  6315606
  10400104
  5775065
  13918738
  14471480
  6108892
Ranlux48:
  111100984774768
  39617518322001
  229495931415673
  101512657299365
  93255382130208
  270337505514216
  74958088628341
  204831462197856
  241244131152007
  20937638821027
  116773688924978
  133388563088659