Branch data Line data Source code
1 : : /* Random objects */
2 : :
3 : : /* ------------------------------------------------------------------
4 : : The code in this module was based on a download from:
5 : : http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html
6 : :
7 : : It was modified in 2002 by Raymond Hettinger as follows:
8 : :
9 : : * the principal computational lines untouched.
10 : :
11 : : * renamed genrand_res53() to random_random() and wrapped
12 : : in python calling/return code.
13 : :
14 : : * genrand_uint32() and the helper functions, init_genrand()
15 : : and init_by_array(), were declared static, wrapped in
16 : : Python calling/return code. also, their global data
17 : : references were replaced with structure references.
18 : :
19 : : * unused functions from the original were deleted.
20 : : new, original C python code was added to implement the
21 : : Random() interface.
22 : :
23 : : The following are the verbatim comments from the original code:
24 : :
25 : : A C-program for MT19937, with initialization improved 2002/1/26.
26 : : Coded by Takuji Nishimura and Makoto Matsumoto.
27 : :
28 : : Before using, initialize the state by using init_genrand(seed)
29 : : or init_by_array(init_key, key_length).
30 : :
31 : : Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
32 : : All rights reserved.
33 : :
34 : : Redistribution and use in source and binary forms, with or without
35 : : modification, are permitted provided that the following conditions
36 : : are met:
37 : :
38 : : 1. Redistributions of source code must retain the above copyright
39 : : notice, this list of conditions and the following disclaimer.
40 : :
41 : : 2. Redistributions in binary form must reproduce the above copyright
42 : : notice, this list of conditions and the following disclaimer in the
43 : : documentation and/or other materials provided with the distribution.
44 : :
45 : : 3. The names of its contributors may not be used to endorse or promote
46 : : products derived from this software without specific prior written
47 : : permission.
48 : :
49 : : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
50 : : "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
51 : : LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
52 : : A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
53 : : CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
54 : : EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
55 : : PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
56 : : PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
57 : : LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
58 : : NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
59 : : SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60 : :
61 : :
62 : : Any feedback is very welcome.
63 : : http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
64 : : email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
65 : : */
66 : :
67 : : /* ---------------------------------------------------------------*/
68 : :
69 : : #ifndef Py_BUILD_CORE_BUILTIN
70 : : # define Py_BUILD_CORE_MODULE 1
71 : : #endif
72 : :
73 : : #include "Python.h"
74 : : #include "pycore_moduleobject.h" // _PyModule_GetState()
75 : : #include "pycore_runtime.h"
76 : : #ifdef HAVE_PROCESS_H
77 : : # include <process.h> // getpid()
78 : : #endif
79 : :
80 : : #ifdef MS_WINDOWS
81 : : # include <windows.h>
82 : : #endif
83 : :
84 : : /* Period parameters -- These are all magic. Don't change. */
85 : : #define N 624
86 : : #define M 397
87 : : #define MATRIX_A 0x9908b0dfU /* constant vector a */
88 : : #define UPPER_MASK 0x80000000U /* most significant w-r bits */
89 : : #define LOWER_MASK 0x7fffffffU /* least significant r bits */
90 : :
91 : : typedef struct {
92 : : PyObject *Random_Type;
93 : : PyObject *Long___abs__;
94 : : } _randomstate;
95 : :
96 : : static inline _randomstate*
97 : 98 : get_random_state(PyObject *module)
98 : : {
99 : 98 : void *state = _PyModule_GetState(module);
100 : : assert(state != NULL);
101 : 98 : return (_randomstate *)state;
102 : : }
103 : :
104 : : static struct PyModuleDef _randommodule;
105 : :
106 : : #define _randomstate_type(type) \
107 : : (get_random_state(PyType_GetModuleByDef(type, &_randommodule)))
108 : :
109 : : typedef struct {
110 : : PyObject_HEAD
111 : : int index;
112 : : uint32_t state[N];
113 : : } RandomObject;
114 : :
115 : :
116 : : #include "clinic/_randommodule.c.h"
117 : :
118 : : /*[clinic input]
119 : : module _random
120 : : class _random.Random "RandomObject *" "_randomstate_type(type)->Random_Type"
121 : : [clinic start generated code]*/
122 : : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=70a2c99619474983]*/
123 : :
124 : : /* Random methods */
125 : :
126 : :
127 : : /* generates a random number on [0,0xffffffff]-interval */
128 : : static uint32_t
129 : 1166521 : genrand_uint32(RandomObject *self)
130 : : {
131 : : uint32_t y;
132 : : static const uint32_t mag01[2] = {0x0U, MATRIX_A};
133 : : /* mag01[x] = x * MATRIX_A for x=0,1 */
134 : : uint32_t *mt;
135 : :
136 : 1166521 : mt = self->state;
137 [ + + ]: 1166521 : if (self->index >= N) { /* generate N words at one time */
138 : : int kk;
139 : :
140 [ + + ]: 426360 : for (kk=0;kk<N-M;kk++) {
141 : 424490 : y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
142 : 424490 : mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1U];
143 : : }
144 [ + + ]: 742390 : for (;kk<N-1;kk++) {
145 : 740520 : y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
146 : 740520 : mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1U];
147 : : }
148 : 1870 : y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
149 : 1870 : mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1U];
150 : :
151 : 1870 : self->index = 0;
152 : : }
153 : :
154 : 1166521 : y = mt[self->index++];
155 : 1166521 : y ^= (y >> 11);
156 : 1166521 : y ^= (y << 7) & 0x9d2c5680U;
157 : 1166521 : y ^= (y << 15) & 0xefc60000U;
158 : 1166521 : y ^= (y >> 18);
159 : 1166521 : return y;
160 : : }
161 : :
162 : : /* random_random is the function named genrand_res53 in the original code;
163 : : * generates a random number on [0,1) with 53-bit resolution; note that
164 : : * 9007199254740992 == 2**53; I assume they're spelling "/2**53" as
165 : : * multiply-by-reciprocal in the (likely vain) hope that the compiler will
166 : : * optimize the division away at compile-time. 67108864 is 2**26. In
167 : : * effect, a contains 27 random bits shifted left 26, and b fills in the
168 : : * lower 26 bits of the 53-bit numerator.
169 : : * The original code credited Isaku Wada for this algorithm, 2002/01/09.
170 : : */
171 : :
172 : : /*[clinic input]
173 : : _random.Random.random
174 : :
175 : : self: self(type="RandomObject *")
176 : :
177 : : random() -> x in the interval [0, 1).
178 : : [clinic start generated code]*/
179 : :
180 : : static PyObject *
181 : 400400 : _random_Random_random_impl(RandomObject *self)
182 : : /*[clinic end generated code: output=117ff99ee53d755c input=afb2a59cbbb00349]*/
183 : : {
184 : 400400 : uint32_t a=genrand_uint32(self)>>5, b=genrand_uint32(self)>>6;
185 : 400400 : return PyFloat_FromDouble((a*67108864.0+b)*(1.0/9007199254740992.0));
186 : : }
187 : :
188 : : /* initializes mt[N] with a seed */
189 : : static void
190 : 1 : init_genrand(RandomObject *self, uint32_t s)
191 : : {
192 : : int mti;
193 : : uint32_t *mt;
194 : :
195 : 1 : mt = self->state;
196 : 1 : mt[0]= s;
197 [ + + ]: 624 : for (mti=1; mti<N; mti++) {
198 : 623 : mt[mti] =
199 : 623 : (1812433253U * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
200 : : /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
201 : : /* In the previous versions, MSBs of the seed affect */
202 : : /* only MSBs of the array mt[]. */
203 : : /* 2002/01/09 modified by Makoto Matsumoto */
204 : : }
205 : 1 : self->index = mti;
206 : 1 : return;
207 : : }
208 : :
209 : : /* initialize by an array with array-length */
210 : : /* init_key is the array for initializing keys */
211 : : /* key_length is its length */
212 : : static void
213 : 1 : init_by_array(RandomObject *self, uint32_t init_key[], size_t key_length)
214 : : {
215 : : size_t i, j, k; /* was signed in the original code. RDH 12/16/2002 */
216 : : uint32_t *mt;
217 : :
218 : 1 : mt = self->state;
219 : 1 : init_genrand(self, 19650218U);
220 : 1 : i=1; j=0;
221 : 1 : k = (N>key_length ? N : key_length);
222 [ + + ]: 625 : for (; k; k--) {
223 : 624 : mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525U))
224 : 624 : + init_key[j] + (uint32_t)j; /* non linear */
225 : 624 : i++; j++;
226 [ + + ]: 624 : if (i>=N) { mt[0] = mt[N-1]; i=1; }
227 [ + + ]: 624 : if (j>=key_length) j=0;
228 : : }
229 [ + + ]: 624 : for (k=N-1; k; k--) {
230 : 623 : mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941U))
231 : 623 : - (uint32_t)i; /* non linear */
232 : 623 : i++;
233 [ + + ]: 623 : if (i>=N) { mt[0] = mt[N-1]; i=1; }
234 : : }
235 : :
236 : 1 : mt[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */
237 : 1 : }
238 : :
239 : : /*
240 : : * The rest is Python-specific code, neither part of, nor derived from, the
241 : : * Twister download.
242 : : */
243 : :
244 : : static int
245 : 1 : random_seed_urandom(RandomObject *self)
246 : : {
247 : : uint32_t key[N];
248 : :
249 [ - + ]: 1 : if (_PyOS_URandomNonblock(key, sizeof(key)) < 0) {
250 : 0 : return -1;
251 : : }
252 : 1 : init_by_array(self, key, Py_ARRAY_LENGTH(key));
253 : 1 : return 0;
254 : : }
255 : :
256 : : static void
257 : 0 : random_seed_time_pid(RandomObject *self)
258 : : {
259 : : _PyTime_t now;
260 : : uint32_t key[5];
261 : :
262 : 0 : now = _PyTime_GetSystemClock();
263 : 0 : key[0] = (uint32_t)(now & 0xffffffffU);
264 : 0 : key[1] = (uint32_t)(now >> 32);
265 : :
266 : : #if defined(MS_WINDOWS) && !defined(MS_WINDOWS_DESKTOP) && !defined(MS_WINDOWS_SYSTEM)
267 : : key[2] = (uint32_t)GetCurrentProcessId();
268 : : #elif defined(HAVE_GETPID)
269 : 0 : key[2] = (uint32_t)getpid();
270 : : #else
271 : : key[2] = 0;
272 : : #endif
273 : :
274 : 0 : now = _PyTime_GetMonotonicClock();
275 : 0 : key[3] = (uint32_t)(now & 0xffffffffU);
276 : 0 : key[4] = (uint32_t)(now >> 32);
277 : :
278 : 0 : init_by_array(self, key, Py_ARRAY_LENGTH(key));
279 : 0 : }
280 : :
281 : : static int
282 : 1 : random_seed(RandomObject *self, PyObject *arg)
283 : : {
284 : 1 : int result = -1; /* guilty until proved innocent */
285 : 1 : PyObject *n = NULL;
286 : 1 : uint32_t *key = NULL;
287 : : size_t bits, keyused;
288 : : int res;
289 : :
290 [ + - + - ]: 1 : if (arg == NULL || arg == Py_None) {
291 [ - + ]: 1 : if (random_seed_urandom(self) < 0) {
292 : 0 : PyErr_Clear();
293 : :
294 : : /* Reading system entropy failed, fall back on the worst entropy:
295 : : use the current time and process identifier. */
296 : 0 : random_seed_time_pid(self);
297 : : }
298 : 1 : return 0;
299 : : }
300 : :
301 : : /* This algorithm relies on the number being unsigned.
302 : : * So: if the arg is a PyLong, use its absolute value.
303 : : * Otherwise use its hash value, cast to unsigned.
304 : : */
305 [ # # ]: 0 : if (PyLong_CheckExact(arg)) {
306 : 0 : n = PyNumber_Absolute(arg);
307 [ # # ]: 0 : } else if (PyLong_Check(arg)) {
308 : : /* Calling int.__abs__() prevents calling arg.__abs__(), which might
309 : : return an invalid value. See issue #31478. */
310 : 0 : _randomstate *state = _randomstate_type(Py_TYPE(self));
311 : 0 : n = PyObject_CallOneArg(state->Long___abs__, arg);
312 : : }
313 : : else {
314 : 0 : Py_hash_t hash = PyObject_Hash(arg);
315 [ # # ]: 0 : if (hash == -1)
316 : 0 : goto Done;
317 : 0 : n = PyLong_FromSize_t((size_t)hash);
318 : : }
319 [ # # ]: 0 : if (n == NULL)
320 : 0 : goto Done;
321 : :
322 : : /* Now split n into 32-bit chunks, from the right. */
323 : 0 : bits = _PyLong_NumBits(n);
324 [ # # # # ]: 0 : if (bits == (size_t)-1 && PyErr_Occurred())
325 : 0 : goto Done;
326 : :
327 : : /* Figure out how many 32-bit chunks this gives us. */
328 [ # # ]: 0 : keyused = bits == 0 ? 1 : (bits - 1) / 32 + 1;
329 : :
330 : : /* Convert seed to byte sequence. */
331 : 0 : key = (uint32_t *)PyMem_Malloc((size_t)4 * keyused);
332 [ # # ]: 0 : if (key == NULL) {
333 : 0 : PyErr_NoMemory();
334 : 0 : goto Done;
335 : : }
336 : 0 : res = _PyLong_AsByteArray((PyLongObject *)n,
337 : : (unsigned char *)key, keyused * 4,
338 : : PY_LITTLE_ENDIAN,
339 : : 0); /* unsigned */
340 [ # # ]: 0 : if (res == -1) {
341 : 0 : goto Done;
342 : : }
343 : :
344 : : #if PY_BIG_ENDIAN
345 : : {
346 : : size_t i, j;
347 : : /* Reverse an array. */
348 : : for (i = 0, j = keyused - 1; i < j; i++, j--) {
349 : : uint32_t tmp = key[i];
350 : : key[i] = key[j];
351 : : key[j] = tmp;
352 : : }
353 : : }
354 : : #endif
355 : 0 : init_by_array(self, key, keyused);
356 : :
357 : 0 : result = 0;
358 : :
359 : 0 : Done:
360 : 0 : Py_XDECREF(n);
361 : 0 : PyMem_Free(key);
362 : 0 : return result;
363 : : }
364 : :
365 : : /*[clinic input]
366 : : _random.Random.seed
367 : :
368 : : self: self(type="RandomObject *")
369 : : n: object = None
370 : : /
371 : :
372 : : seed([n]) -> None.
373 : :
374 : : Defaults to use urandom and falls back to a combination
375 : : of the current time and the process identifier.
376 : : [clinic start generated code]*/
377 : :
378 : : static PyObject *
379 : 1 : _random_Random_seed_impl(RandomObject *self, PyObject *n)
380 : : /*[clinic end generated code: output=0fad1e16ba883681 input=78d6ef0d52532a54]*/
381 : : {
382 [ - + ]: 1 : if (random_seed(self, n) < 0) {
383 : 0 : return NULL;
384 : : }
385 : 1 : Py_RETURN_NONE;
386 : : }
387 : :
388 : : /*[clinic input]
389 : : _random.Random.getstate
390 : :
391 : : self: self(type="RandomObject *")
392 : :
393 : : getstate() -> tuple containing the current state.
394 : : [clinic start generated code]*/
395 : :
396 : : static PyObject *
397 : 0 : _random_Random_getstate_impl(RandomObject *self)
398 : : /*[clinic end generated code: output=bf6cef0c092c7180 input=b937a487928c0e89]*/
399 : : {
400 : : PyObject *state;
401 : : PyObject *element;
402 : : int i;
403 : :
404 : 0 : state = PyTuple_New(N+1);
405 [ # # ]: 0 : if (state == NULL)
406 : 0 : return NULL;
407 [ # # ]: 0 : for (i=0; i<N ; i++) {
408 : 0 : element = PyLong_FromUnsignedLong(self->state[i]);
409 [ # # ]: 0 : if (element == NULL)
410 : 0 : goto Fail;
411 : 0 : PyTuple_SET_ITEM(state, i, element);
412 : : }
413 : 0 : element = PyLong_FromLong((long)(self->index));
414 [ # # ]: 0 : if (element == NULL)
415 : 0 : goto Fail;
416 : 0 : PyTuple_SET_ITEM(state, i, element);
417 : 0 : return state;
418 : :
419 : 0 : Fail:
420 : 0 : Py_DECREF(state);
421 : 0 : return NULL;
422 : : }
423 : :
424 : :
425 : : /*[clinic input]
426 : : _random.Random.setstate
427 : :
428 : : self: self(type="RandomObject *")
429 : : state: object
430 : : /
431 : :
432 : : setstate(state) -> None. Restores generator state.
433 : : [clinic start generated code]*/
434 : :
435 : : static PyObject *
436 : 0 : _random_Random_setstate(RandomObject *self, PyObject *state)
437 : : /*[clinic end generated code: output=fd1c3cd0037b6681 input=b3b4efbb1bc66af8]*/
438 : : {
439 : : int i;
440 : : unsigned long element;
441 : : long index;
442 : : uint32_t new_state[N];
443 : :
444 [ # # ]: 0 : if (!PyTuple_Check(state)) {
445 : 0 : PyErr_SetString(PyExc_TypeError,
446 : : "state vector must be a tuple");
447 : 0 : return NULL;
448 : : }
449 [ # # ]: 0 : if (PyTuple_Size(state) != N+1) {
450 : 0 : PyErr_SetString(PyExc_ValueError,
451 : : "state vector is the wrong size");
452 : 0 : return NULL;
453 : : }
454 : :
455 [ # # ]: 0 : for (i=0; i<N ; i++) {
456 : 0 : element = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(state, i));
457 [ # # # # ]: 0 : if (element == (unsigned long)-1 && PyErr_Occurred())
458 : 0 : return NULL;
459 : 0 : new_state[i] = (uint32_t)element;
460 : : }
461 : :
462 : 0 : index = PyLong_AsLong(PyTuple_GET_ITEM(state, i));
463 [ # # # # ]: 0 : if (index == -1 && PyErr_Occurred())
464 : 0 : return NULL;
465 [ # # # # ]: 0 : if (index < 0 || index > N) {
466 : 0 : PyErr_SetString(PyExc_ValueError, "invalid state");
467 : 0 : return NULL;
468 : : }
469 : 0 : self->index = (int)index;
470 [ # # ]: 0 : for (i = 0; i < N; i++)
471 : 0 : self->state[i] = new_state[i];
472 : :
473 : 0 : Py_RETURN_NONE;
474 : : }
475 : :
476 : : /*[clinic input]
477 : :
478 : : _random.Random.getrandbits
479 : :
480 : : self: self(type="RandomObject *")
481 : : k: int
482 : : /
483 : :
484 : : getrandbits(k) -> x. Generates an int with k random bits.
485 : : [clinic start generated code]*/
486 : :
487 : : static PyObject *
488 : 365721 : _random_Random_getrandbits_impl(RandomObject *self, int k)
489 : : /*[clinic end generated code: output=b402f82a2158887f input=8c0e6396dd176fc0]*/
490 : : {
491 : : int i, words;
492 : : uint32_t r;
493 : : uint32_t *wordarray;
494 : : PyObject *result;
495 : :
496 [ - + ]: 365721 : if (k < 0) {
497 : 0 : PyErr_SetString(PyExc_ValueError,
498 : : "number of bits must be non-negative");
499 : 0 : return NULL;
500 : : }
501 : :
502 [ - + ]: 365721 : if (k == 0)
503 : 0 : return PyLong_FromLong(0);
504 : :
505 [ + - ]: 365721 : if (k <= 32) /* Fast path */
506 : 365721 : return PyLong_FromUnsignedLong(genrand_uint32(self) >> (32 - k));
507 : :
508 : 0 : words = (k - 1) / 32 + 1;
509 : 0 : wordarray = (uint32_t *)PyMem_Malloc(words * 4);
510 [ # # ]: 0 : if (wordarray == NULL) {
511 : 0 : PyErr_NoMemory();
512 : 0 : return NULL;
513 : : }
514 : :
515 : : /* Fill-out bits of long integer, by 32-bit words, from least significant
516 : : to most significant. */
517 : : #if PY_LITTLE_ENDIAN
518 [ # # ]: 0 : for (i = 0; i < words; i++, k -= 32)
519 : : #else
520 : : for (i = words - 1; i >= 0; i--, k -= 32)
521 : : #endif
522 : : {
523 : 0 : r = genrand_uint32(self);
524 [ # # ]: 0 : if (k < 32)
525 : 0 : r >>= (32 - k); /* Drop least significant bits */
526 : 0 : wordarray[i] = r;
527 : : }
528 : :
529 : 0 : result = _PyLong_FromByteArray((unsigned char *)wordarray, words * 4,
530 : : PY_LITTLE_ENDIAN, 0 /* unsigned */);
531 : 0 : PyMem_Free(wordarray);
532 : 0 : return result;
533 : : }
534 : :
535 : : static int
536 : 0 : random_init(RandomObject *self, PyObject *args, PyObject *kwds)
537 : : {
538 : 0 : PyObject *arg = NULL;
539 : 0 : _randomstate *state = _randomstate_type(Py_TYPE(self));
540 : :
541 [ # # ]: 0 : if ((Py_IS_TYPE(self, (PyTypeObject *)state->Random_Type) ||
542 [ # # # # ]: 0 : Py_TYPE(self)->tp_init == ((PyTypeObject*)state->Random_Type)->tp_init) &&
543 [ # # ]: 0 : !_PyArg_NoKeywords("Random", kwds)) {
544 : 0 : return -1;
545 : : }
546 : :
547 [ # # ]: 0 : if (PyTuple_GET_SIZE(args) > 1) {
548 : 0 : PyErr_SetString(PyExc_TypeError, "Random() requires 0 or 1 argument");
549 : 0 : return -1;
550 : : }
551 : :
552 [ # # ]: 0 : if (PyTuple_GET_SIZE(args) == 1)
553 : 0 : arg = PyTuple_GET_ITEM(args, 0);
554 : :
555 : 0 : return random_seed(self, arg);
556 : : }
557 : :
558 : :
559 : : static PyMethodDef random_methods[] = {
560 : : _RANDOM_RANDOM_RANDOM_METHODDEF
561 : : _RANDOM_RANDOM_SEED_METHODDEF
562 : : _RANDOM_RANDOM_GETSTATE_METHODDEF
563 : : _RANDOM_RANDOM_SETSTATE_METHODDEF
564 : : _RANDOM_RANDOM_GETRANDBITS_METHODDEF
565 : : {NULL, NULL} /* sentinel */
566 : : };
567 : :
568 : : PyDoc_STRVAR(random_doc,
569 : : "Random() -> create a random number generator with its own internal state.");
570 : :
571 : : static PyType_Slot Random_Type_slots[] = {
572 : : {Py_tp_doc, (void *)random_doc},
573 : : {Py_tp_methods, random_methods},
574 : : {Py_tp_new, PyType_GenericNew},
575 : : {Py_tp_init, random_init},
576 : : {Py_tp_free, PyObject_Free},
577 : : {0, 0},
578 : : };
579 : :
580 : : static PyType_Spec Random_Type_spec = {
581 : : "_random.Random",
582 : : sizeof(RandomObject),
583 : : 0,
584 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
585 : : Random_Type_slots
586 : : };
587 : :
588 : : PyDoc_STRVAR(module_doc,
589 : : "Module implements the Mersenne Twister random number generator.");
590 : :
591 : : static int
592 : 2 : _random_exec(PyObject *module)
593 : : {
594 : 2 : _randomstate *state = get_random_state(module);
595 : :
596 : 2 : state->Random_Type = PyType_FromModuleAndSpec(
597 : : module, &Random_Type_spec, NULL);
598 [ - + ]: 2 : if (state->Random_Type == NULL) {
599 : 0 : return -1;
600 : : }
601 [ - + ]: 2 : if (PyModule_AddType(module, (PyTypeObject *)state->Random_Type) < 0) {
602 : 0 : return -1;
603 : : }
604 : :
605 : : /* Look up and save int.__abs__, which is needed in random_seed(). */
606 : 2 : PyObject *longval = PyLong_FromLong(0);
607 [ - + ]: 2 : if (longval == NULL) {
608 : 0 : return -1;
609 : : }
610 : :
611 : 2 : PyObject *longtype = PyObject_Type(longval);
612 : 2 : Py_DECREF(longval);
613 [ - + ]: 2 : if (longtype == NULL) {
614 : 0 : return -1;
615 : : }
616 : :
617 : 2 : state->Long___abs__ = PyObject_GetAttrString(longtype, "__abs__");
618 : 2 : Py_DECREF(longtype);
619 [ - + ]: 2 : if (state->Long___abs__ == NULL) {
620 : 0 : return -1;
621 : : }
622 : 2 : return 0;
623 : : }
624 : :
625 : : static PyModuleDef_Slot _random_slots[] = {
626 : : {Py_mod_exec, _random_exec},
627 : : {0, NULL}
628 : : };
629 : :
630 : : static int
631 : 44 : _random_traverse(PyObject *module, visitproc visit, void *arg)
632 : : {
633 [ + - - + ]: 44 : Py_VISIT(get_random_state(module)->Random_Type);
634 : 44 : return 0;
635 : : }
636 : :
637 : : static int
638 : 4 : _random_clear(PyObject *module)
639 : : {
640 [ + + ]: 4 : Py_CLEAR(get_random_state(module)->Random_Type);
641 [ + + ]: 4 : Py_CLEAR(get_random_state(module)->Long___abs__);
642 : 4 : return 0;
643 : : }
644 : :
645 : : static void
646 : 2 : _random_free(void *module)
647 : : {
648 : 2 : _random_clear((PyObject *)module);
649 : 2 : }
650 : :
651 : : static struct PyModuleDef _randommodule = {
652 : : PyModuleDef_HEAD_INIT,
653 : : "_random",
654 : : module_doc,
655 : : sizeof(_randomstate),
656 : : NULL,
657 : : _random_slots,
658 : : _random_traverse,
659 : : _random_clear,
660 : : _random_free,
661 : : };
662 : :
663 : : PyMODINIT_FUNC
664 : 2 : PyInit__random(void)
665 : : {
666 : 2 : return PyModuleDef_Init(&_randommodule);
667 : : }
|