LCOV - code coverage report
Current view: | top level - Modules - _randommodule.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 95 | 210 | 45.2 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 14 | 18 | 77.8 %
|  |  | Branches: | 37 | 116 | 31.9 %

               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                 :            : }

Generated by: LCOV version 1.14