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