cryptopals

https://cryptopals.com/
Log | Files | Refs

mt19937.py (1465B)


      1 def _int32(x):
      2     # Get the 32 least significant bits.
      3     return int(0xffffffff & x)
      4 
      5 class MersenneTwister:
      6 
      7     def __init__(self, seed):
      8         # Initialize the index to 0
      9         self.index = 624
     10         self.mt = [0] * 624
     11         self.mt[0] = seed  # Initialize the initial state to the seed
     12         for i in range(1, 624):
     13             self.mt[i] = _int32(
     14                 1812433253 * (self.mt[i - 1] ^ self.mt[i - 1] >> 30) + i)
     15 
     16     def set_state(self, cloned_state):
     17         self.mt = cloned_state
     18 
     19     def extract_number(self):
     20         if self.index >= 624:
     21             self.twist()
     22 
     23         y = self.mt[self.index]
     24 
     25         # Right shift by 11 bits
     26         y = y ^ y >> 11
     27         # Shift y left by 7 and take the bitwise and of 2636928640
     28         y = y ^ y << 7 & 2636928640
     29         # Shift y left by 15 and take the bitwise and of y and 4022730752
     30         y = y ^ y << 15 & 4022730752
     31         # Right shift by 18 bits
     32         y = y ^ y >> 18
     33 
     34         self.index = self.index + 1
     35 
     36         return _int32(y)
     37 
     38     def twist(self):
     39         for i in range(624):
     40             # Get the most significant bit and add it to the less significant
     41             # bits of the next number
     42             y = _int32((self.mt[i] & 0x80000000) +
     43                        (self.mt[(i + 1) % 624] & 0x7fffffff))
     44             self.mt[i] = self.mt[(i + 397) % 624] ^ y >> 1
     45 
     46             if y % 2 != 0:
     47                 self.mt[i] = self.mt[i] ^ 0x9908b0df
     48         self.index = 0