definvertStep(si, si227): # S[i] ^ S[i-227] == (((I[i] & 0x80000000) | (I[i+1] & 0x7FFFFFFF)) >> 1) ^ (0x9908b0df if I[i+1] & 1 else 0) X = si ^ si227 # we know the LSB of I[i+1] because MSB of 0x9908b0df is set, we can see if the XOR has been applied mti1 = (X & 0x80000000) >> 31 if mti1: X ^= 0x9908b0df # undo shift right X <<= 1 # now recover MSB of state I[i] mti = X & 0x80000000 # recover the rest of state I[i+1] mti1 += X & 0x7FFFFFFF return mti, mti1
definvertStep(si, si227): # S[i] ^ S[i-227] == (((I[i] & 0x80000000) | (I[i+1] & 0x7FFFFFFF)) >> 1) ^ (0x9908b0df if I[i+1] & 1 else 0) X = si ^ si227 # we know the LSB of I[i+1] because MSB of 0x9908b0df is set, we can see if the XOR has been applied mti1 = (X & 0x80000000) >> 31 if mti1: X ^= 0x9908b0df # undo shift right X <<= 1 # now recover MSB of state I[i] mti = X & 0x80000000 # recover the rest of state I[i+1] mti1 += X & 0x7FFFFFFF return mti, mti1
I = random.getstate()[1] # this will force a state update random.random() S = random.getstate()[1]
for i inrange(227, 240): Ii, Ii1 = invertStep(S[i], S[i-227]) print(f"{Ii} == {I[i]&0x80000000}") print(f"{Ii1} == {I[i+1]&0x7FFFFFFF}")
classRandom(_random.Random): defseed(self, a=None, version=2): """Initialize internal state from a seed. The only supported seed types are None, int, float, str, bytes, and bytearray. None or no argument seeds from current time or from an operating system specific randomness source if available. If *a* is an int, all bits are used. For version 2 (the default), all of the bits are used if *a* is a str, bytes, or bytearray. For version 1 (provided for reproducing random sequences from older versions of Python), the algorithm for str and bytes generates a narrower range of seeds. """
if version == 1andisinstance(a, (str, bytes)): a = a.decode('latin-1') ifisinstance(a, bytes) else a x = ord(a[0]) << 7if a else0 for c inmap(ord, a): x = ((1000003 * x) ^ c) & 0xFFFFFFFFFFFFFFFF x ^= len(a) a = -2if x == -1else x
elif version == 2andisinstance(a, (str, bytes, bytearray)): ifisinstance(a, str): a = a.encode() a = int.from_bytes(a + _sha512(a).digest(), 'big')
elifnotisinstance(a, (type(None), int, float, str, bytes, bytearray)): _warn('Seeding based on hashing is deprecated\n' 'since Python 3.9 and will be removed in a subsequent ' 'version. The only \n' 'supported seed types are: None, ' 'int, float, str, bytes, and bytearray.', DeprecationWarning, 2)
if (arg == NULL || arg == Py_None) { if (random_seed_urandom(self) < 0) { PyErr_Clear();
/* Reading system entropy failed, fall back on the worst entropy: use the current time and process identifier. */ if (random_seed_time_pid(self) < 0) { return-1; } } return0; }
/* This algorithm relies on the number being unsigned. * So: if the arg is a PyLong, use its absolute value. * Otherwise use its hash value, cast to unsigned. */ if (PyLong_CheckExact(arg)) { n = PyNumber_Absolute(arg); } elseif (PyLong_Check(arg)) { /* Calling int.__abs__() prevents calling arg.__abs__(), which might return an invalid value. See issue #31478. */ _randomstate *state = _randomstate_type(Py_TYPE(self)); n = PyObject_CallOneArg(state->Long___abs__, arg); } else { Py_hash_t hash = PyObject_Hash(arg); if (hash == -1) goto Done; n = PyLong_FromSize_t((size_t)hash); } if (n == NULL) goto Done;
/* Now split n into 32-bit chunks, from the right. */ bits = _PyLong_NumBits(n); if (bits == (size_t)-1 && PyErr_Occurred()) goto Done;
/* Figure out how many 32-bit chunks this gives us. */ keyused = bits == 0 ? 1 : (bits - 1) / 32 + 1;
/* Convert seed to byte sequence. */ key = (uint32_t *)PyMem_Malloc((size_t)4 * keyused); if (key == NULL) { PyErr_NoMemory(); goto Done; } res = _PyLong_AsByteArray((PyLongObject *)n, (unsignedchar *)key, keyused * 4, PY_LITTLE_ENDIAN, 0, /* unsigned */ 1); /* with exceptions */ if (res == -1) { goto Done; }
/* initialize by an array with array-length */ /* init_key is the array for initializing keys */ /* key_length is its length */ staticvoid init_by_array(RandomObject *self, uint32_t init_key[], size_t key_length) { size_t i, j, k, l; /* was signed in the original code. RDH 12/16/2002 */ uint32_t *mt;
mt = self->state; init_genrand(self, 19650218U); i=1; j=0; k = (N>key_length ? N : key_length);
for (; k; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525U)) + init_key[j] + (uint32_t)j; /* non linear */ i++; j++; if (i>=N) { mt[0] = mt[N-1]; i=1; } if (j>=key_length) j=0; }
for (k=N-1; k; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941U)) - (uint32_t)i; /* non linear */ i++; if (i>=N) { mt[0] = mt[N-1]; i=1; } }
defunshiftRight(x, shift): res = x for i inrange(32): res = x ^ res >> shift return res
defunshiftLeft(x, shift, mask): res = x for i inrange(32): res = x ^ (res << shift & mask) return res
defuntemper(v): v = unshiftRight(v, 18) v = unshiftLeft(v, 15, 0xefc60000) v = unshiftLeft(v, 7, 0x9d2c5680) v = unshiftRight(v, 11) return v
definvertStep(si, si227): # S[i] ^ S[i-227] == (((I[i] & 0x80000000) | (I[i+1] & 0x7FFFFFFF)) >> 1) ^ (0x9908b0df if I[i+1] & 1 else 0) X = si ^ si227 # we know the LSB of I[i+1] because MSB of 0x9908b0df is set, we can see if the XOR has been applied mti1 = (X & 0x80000000) >> 31 if mti1: X ^= 0x9908b0df # undo shift right X <<= 1 # now recover MSB of state I[i] mti = X & 0x80000000 # recover the rest of state I[i+1] mti1 += X & 0x7FFFFFFF return mti, mti1
definit_genrand(seed): MT = [0] * 624 MT[0] = seed & 0xffffffff for i inrange(1, 623 + 1): # loop over each element MT[i] = ((0x6c078965 * (MT[i - 1] ^ (MT[i - 1] >> 30))) + i) & 0xffffffff return MT
defrewindState(state): prev = [0]*624 # copy to not modify input array s = state[:] I, I0 = invertStep(s[623], s[396]) prev[623] += I # update state 0 # this does nothing when working with a known full state, but is important we rewinding more than 1 time s[0] = (s[0]&0x80000000) + I0 for i inrange(227, 623): I, I1 = invertStep(s[i], s[i-227]) prev[i] += I prev[i+1] += I1 for i inrange(227): I, I1 = invertStep(s[i], prev[i+397]) prev[i] += I prev[i+1] += I1 # The LSBs of prev[0] do not matter, they are 0 here return prev
defunshiftRight(x, shift): res = x for i inrange(32): res = x ^ res >> shift return res
defunshiftLeft(x, shift, mask): res = x for i inrange(32): res = x ^ (res << shift & mask) return res
defuntemper(v): v = unshiftRight(v, 18) v = unshiftLeft(v, 15, 0xefc60000) v = unshiftLeft(v, 7, 0x9d2c5680) v = unshiftRight(v, 11) return v
definvertStep(si, si227): # S[i] ^ S[i-227] == (((I[i] & 0x80000000) | (I[i+1] & 0x7FFFFFFF)) >> 1) ^ (0x9908b0df if I[i+1] & 1 else 0) X = si ^ si227 # we know the LSB of I[i+1] because MSB of 0x9908b0df is set, we can see if the XOR has been applied mti1 = (X & 0x80000000) >> 31 if mti1: X ^= 0x9908b0df # undo shift right X <<= 1 # now recover MSB of state I[i] mti = X & 0x80000000 # recover the rest of state I[i+1] mti1 += X & 0x7FFFFFFF return mti, mti1
defrewindState(state): prev = [0]*624 # copy to not modify input array s = state[:] I, I0 = invertStep(s[623], s[396]) prev[623] += I # update state 0 # this does nothing when working with a known full state, but is important we rewinding more than 1 time s[0] = (s[0]&0x80000000) + I0 for i inrange(227, 623): I, I1 = invertStep(s[i], s[i-227]) prev[i] += I prev[i+1] += I1 for i inrange(227): I, I1 = invertStep(s[i], prev[i+397]) prev[i] += I prev[i+1] += I1 # The LSBs of prev[0] do not matter, they are 0 here return prev
I = list(random.getstate()[1][:-1])
S1 = [untemper(random.getrandbits(32)) for _ inrange(624)] S2 = [untemper(random.getrandbits(32)) for _ inrange(624)] S3 = [untemper(random.getrandbits(32)) for _ inrange(624)]