Python Random Module
seed
static PyObject *_random_Random_seed_impl(RandomObject *self, PyObject *n) {
if (random_seed(self, n) < 0) {
return NULL;
}
// #define Py_RETURN_NONE return Py_None
Py_RETURN_NONE;
}
static int random_seed(RandomObject *self, PyObject *arg) {
int result = -1;
PyObject *n = NULL;
uint32_t *key = NULL;
size_t bits, keyused;
int res;
if (arg == NULL || arg == Py_None) {
// ...
}
if (PyLong_CheckExact(arg)) {
n = PyNumber_Absolute(arg);
} else if (PyLong_Check(arg)) {
// ...
} else {
// ...
}
if (n == NULL)
goto Done;
bits = _PyLong_NumBits(n);
if (bits == (size_t)-1 && PyErr_Occurred())
goto Done;
// 找出 `n` 總共需要多少 32 bits 的 chunk
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
}
// 把 `n` 的值按照 little endian 排進 `key`,倒數第二個 0 代表 unsigned,倒數第一個 1 代表有錯誤會有 exeption
res = _PyLong_AsByteArray((PyLongObject *)n, (unsigned char *)key, keyused * 4, PY_LITTLE_ENDIAN, 0, 1);
if (res == -1) {
goto Done;
}
#if PY_BIG_ENDIAN
// 把 `key` 反過來
{
size_t i, j;
for (i = 0, j = keyused - 1; i < j; i++, j--) {
uint32_t tmp = key[i];
key[i] = key[j];
key[j] = tmp;
}
}
#endif
init_by_array(self, key, keyused);
result = 0;
Done:
Py_XDECREF(n);
PyMem_Free(key);
return result;
}
static void init_by_array(RandomObject *self, uint32_t init_key[], size_t key_length) {
size_t i, j, k;
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;
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;
i++;
if (i >= N) { mt[0] = mt[N-1]; i=1; }
}
mt[0] = 0x80000000U;
}
static void init_genrand(RandomObject *self, uint32_t s) {
int mti;
uint32_t *mt;
mt = self->state;
mt[0] = s;
// #define N 624
for (mti = 1; mti < N; mti++) {
mt[mti] = (1812433253U * (mt[mti - 1] ^ (mt[mti - 1] >> 30)) + mti);
}
self->index = mti;
return;
}
getrandbits
static PyObject *_random_Random_getrandbits_impl(RandomObject *self, int k) {
int i, words;
uint32_t r;
uint32_t *wordarray;
PyObject *result;
if (k < 0) {
PyErr_SetString(PyExc_ValueError, "number of bits must be non-negative");
return NULL;
}
if (k == 0)
return PyLong_FromLong(0);
if (k <= 32)
return PyLong_FromUnsignedLong(genrand_uint32(self) >> (32 - k));
words = (k - 1) / 32 + 1;
wordarray = (uint32_t *)PyMem_Malloc(words * 4);
if (wordarray == NULL) {
PyErr_NoMemory();
return NULL;
}
#if PY_LITTLE_ENDIAN
for (i = 0; i < words; i++, k -= 32)
#else
for (i = words - 1; i >= 0; i--, k -= 32)
#endif
{
r = genrand_uint32(self);
if (k < 32)
r >>= (32 - k); /* Drop least significant bits */
wordarray[i] = r;
}
result = _PyLong_FromByteArray((unsigned char *)wordarray, words * 4, PY_LITTLE_ENDIAN, 0);
PyMem_Free(wordarray);
return result;
}
static uint32_t
genrand_uint32(RandomObject *self)
{
uint32_t y;
// #define MATRIX_A 0x9908b0dfU
static const uint32_t mag01[2] = {0x0U, MATRIX_A};
uint32_t *mt;
mt = self->state;
if (self->index >= N) {
int kk;
// #define M 397
// #define UPPER_MASK 0x80000000U
// #define LOWER_MASK 0x7fffffffU
for (kk = 0; kk < N-M; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1U];
}
for (; kk < N-1; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk+1] & LOWER_MASK);
mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1U];
}
y = (mt[N-1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1U];
self->index = 0;
}
y = mt[self->index++];
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680U;
y ^= (y << 15) & 0xefc60000U;
y ^= (y >> 18);
return y;
}