LCOV - code coverage report
Current view: top level - Modules - _randommodule.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 169 208 81.2 %
Date: 2022-07-20 13:12:14 Functions: 17 18 94.4 %
Branches: 80 116 69.0 %

           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                 :            : #ifdef HAVE_PROCESS_H
      76                 :            : #  include <process.h>            // getpid()
      77                 :            : #endif
      78                 :            : 
      79                 :            : /* Period parameters -- These are all magic.  Don't change. */
      80                 :            : #define N 624
      81                 :            : #define M 397
      82                 :            : #define MATRIX_A 0x9908b0dfU    /* constant vector a */
      83                 :            : #define UPPER_MASK 0x80000000U  /* most significant w-r bits */
      84                 :            : #define LOWER_MASK 0x7fffffffU  /* least significant r bits */
      85                 :            : 
      86                 :            : typedef struct {
      87                 :            :     PyObject *Random_Type;
      88                 :            :     PyObject *Long___abs__;
      89                 :            : } _randomstate;
      90                 :            : 
      91                 :            : static inline _randomstate*
      92                 :      89142 : get_random_state(PyObject *module)
      93                 :            : {
      94                 :      89142 :     void *state = _PyModule_GetState(module);
      95                 :            :     assert(state != NULL);
      96                 :      89142 :     return (_randomstate *)state;
      97                 :            : }
      98                 :            : 
      99                 :            : static struct PyModuleDef _randommodule;
     100                 :            : 
     101                 :            : #define _randomstate_type(type) \
     102                 :            :     (get_random_state(PyType_GetModuleByDef(type, &_randommodule)))
     103                 :            : 
     104                 :            : typedef struct {
     105                 :            :     PyObject_HEAD
     106                 :            :     int index;
     107                 :            :     uint32_t state[N];
     108                 :            : } RandomObject;
     109                 :            : 
     110                 :            : 
     111                 :            : #include "clinic/_randommodule.c.h"
     112                 :            : 
     113                 :            : /*[clinic input]
     114                 :            : module _random
     115                 :            : class _random.Random "RandomObject *" "_randomstate_type(type)->Random_Type"
     116                 :            : [clinic start generated code]*/
     117                 :            : /*[clinic end generated code: output=da39a3ee5e6b4b0d input=70a2c99619474983]*/
     118                 :            : 
     119                 :            : /* Random methods */
     120                 :            : 
     121                 :            : 
     122                 :            : /* generates a random number on [0,0xffffffff]-interval */
     123                 :            : static uint32_t
     124                 :   39864878 : genrand_uint32(RandomObject *self)
     125                 :            : {
     126                 :            :     uint32_t y;
     127                 :            :     static const uint32_t mag01[2] = {0x0U, MATRIX_A};
     128                 :            :     /* mag01[x] = x * MATRIX_A  for x=0,1 */
     129                 :            :     uint32_t *mt;
     130                 :            : 
     131                 :   39864878 :     mt = self->state;
     132         [ +  + ]:   39864878 :     if (self->index >= N) { /* generate N words at one time */
     133                 :            :         int kk;
     134                 :            : 
     135         [ +  + ]:   14728800 :         for (kk=0;kk<N-M;kk++) {
     136                 :   14664200 :             y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
     137                 :   14664200 :             mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1U];
     138                 :            :         }
     139         [ +  + ]:   25646200 :         for (;kk<N-1;kk++) {
     140                 :   25581600 :             y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
     141                 :   25581600 :             mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1U];
     142                 :            :         }
     143                 :      64600 :         y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
     144                 :      64600 :         mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1U];
     145                 :            : 
     146                 :      64600 :         self->index = 0;
     147                 :            :     }
     148                 :            : 
     149                 :   39864878 :     y = mt[self->index++];
     150                 :   39864878 :     y ^= (y >> 11);
     151                 :   39864878 :     y ^= (y << 7) & 0x9d2c5680U;
     152                 :   39864878 :     y ^= (y << 15) & 0xefc60000U;
     153                 :   39864878 :     y ^= (y >> 18);
     154                 :   39864878 :     return y;
     155                 :            : }
     156                 :            : 
     157                 :            : /* random_random is the function named genrand_res53 in the original code;
     158                 :            :  * generates a random number on [0,1) with 53-bit resolution; note that
     159                 :            :  * 9007199254740992 == 2**53; I assume they're spelling "/2**53" as
     160                 :            :  * multiply-by-reciprocal in the (likely vain) hope that the compiler will
     161                 :            :  * optimize the division away at compile-time.  67108864 is 2**26.  In
     162                 :            :  * effect, a contains 27 random bits shifted left 26, and b fills in the
     163                 :            :  * lower 26 bits of the 53-bit numerator.
     164                 :            :  * The original code credited Isaku Wada for this algorithm, 2002/01/09.
     165                 :            :  */
     166                 :            : 
     167                 :            : /*[clinic input]
     168                 :            : _random.Random.random
     169                 :            : 
     170                 :            :   self: self(type="RandomObject *")
     171                 :            : 
     172                 :            : random() -> x in the interval [0, 1).
     173                 :            : [clinic start generated code]*/
     174                 :            : 
     175                 :            : static PyObject *
     176                 :    9557391 : _random_Random_random_impl(RandomObject *self)
     177                 :            : /*[clinic end generated code: output=117ff99ee53d755c input=afb2a59cbbb00349]*/
     178                 :            : {
     179                 :    9557391 :     uint32_t a=genrand_uint32(self)>>5, b=genrand_uint32(self)>>6;
     180                 :    9557391 :     return PyFloat_FromDouble((a*67108864.0+b)*(1.0/9007199254740992.0));
     181                 :            : }
     182                 :            : 
     183                 :            : /* initializes mt[N] with a seed */
     184                 :            : static void
     185                 :       1876 : init_genrand(RandomObject *self, uint32_t s)
     186                 :            : {
     187                 :            :     int mti;
     188                 :            :     uint32_t *mt;
     189                 :            : 
     190                 :       1876 :     mt = self->state;
     191                 :       1876 :     mt[0]= s;
     192         [ +  + ]:    1170624 :     for (mti=1; mti<N; mti++) {
     193                 :    1168748 :         mt[mti] =
     194                 :    1168748 :         (1812433253U * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
     195                 :            :         /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
     196                 :            :         /* In the previous versions, MSBs of the seed affect   */
     197                 :            :         /* only MSBs of the array mt[].                                */
     198                 :            :         /* 2002/01/09 modified by Makoto Matsumoto                     */
     199                 :            :     }
     200                 :       1876 :     self->index = mti;
     201                 :       1876 :     return;
     202                 :            : }
     203                 :            : 
     204                 :            : /* initialize by an array with array-length */
     205                 :            : /* init_key is the array for initializing keys */
     206                 :            : /* key_length is its length */
     207                 :            : static void
     208                 :       1876 : init_by_array(RandomObject *self, uint32_t init_key[], size_t key_length)
     209                 :            : {
     210                 :            :     size_t i, j, k;       /* was signed in the original code. RDH 12/16/2002 */
     211                 :            :     uint32_t *mt;
     212                 :            : 
     213                 :       1876 :     mt = self->state;
     214                 :       1876 :     init_genrand(self, 19650218U);
     215                 :       1876 :     i=1; j=0;
     216                 :       1876 :     k = (N>key_length ? N : key_length);
     217         [ +  + ]:    1174376 :     for (; k; k--) {
     218                 :    1172500 :         mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525U))
     219                 :    1172500 :                  + init_key[j] + (uint32_t)j; /* non linear */
     220                 :    1172500 :         i++; j++;
     221         [ +  + ]:    1172500 :         if (i>=N) { mt[0] = mt[N-1]; i=1; }
     222         [ +  + ]:    1172500 :         if (j>=key_length) j=0;
     223                 :            :     }
     224         [ +  + ]:    1170624 :     for (k=N-1; k; k--) {
     225                 :    1168748 :         mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941U))
     226                 :    1168748 :                  - (uint32_t)i; /* non linear */
     227                 :    1168748 :         i++;
     228         [ +  + ]:    1168748 :         if (i>=N) { mt[0] = mt[N-1]; i=1; }
     229                 :            :     }
     230                 :            : 
     231                 :       1876 :     mt[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */
     232                 :       1876 : }
     233                 :            : 
     234                 :            : /*
     235                 :            :  * The rest is Python-specific code, neither part of, nor derived from, the
     236                 :            :  * Twister download.
     237                 :            :  */
     238                 :            : 
     239                 :            : static int
     240                 :       1757 : random_seed_urandom(RandomObject *self)
     241                 :            : {
     242                 :            :     uint32_t key[N];
     243                 :            : 
     244         [ -  + ]:       1757 :     if (_PyOS_URandomNonblock(key, sizeof(key)) < 0) {
     245                 :          0 :         return -1;
     246                 :            :     }
     247                 :       1757 :     init_by_array(self, key, Py_ARRAY_LENGTH(key));
     248                 :       1757 :     return 0;
     249                 :            : }
     250                 :            : 
     251                 :            : static void
     252                 :          0 : random_seed_time_pid(RandomObject *self)
     253                 :            : {
     254                 :            :     _PyTime_t now;
     255                 :            :     uint32_t key[5];
     256                 :            : 
     257                 :          0 :     now = _PyTime_GetSystemClock();
     258                 :          0 :     key[0] = (uint32_t)(now & 0xffffffffU);
     259                 :          0 :     key[1] = (uint32_t)(now >> 32);
     260                 :            : 
     261                 :            : #ifdef HAVE_GETPID
     262                 :          0 :     key[2] = (uint32_t)getpid();
     263                 :            : #else
     264                 :            :     key[2] = 0;
     265                 :            : #endif
     266                 :            : 
     267                 :          0 :     now = _PyTime_GetMonotonicClock();
     268                 :          0 :     key[3] = (uint32_t)(now & 0xffffffffU);
     269                 :          0 :     key[4] = (uint32_t)(now >> 32);
     270                 :            : 
     271                 :          0 :     init_by_array(self, key, Py_ARRAY_LENGTH(key));
     272                 :          0 : }
     273                 :            : 
     274                 :            : static int
     275                 :       1876 : random_seed(RandomObject *self, PyObject *arg)
     276                 :            : {
     277                 :       1876 :     int result = -1;  /* guilty until proved innocent */
     278                 :       1876 :     PyObject *n = NULL;
     279                 :       1876 :     uint32_t *key = NULL;
     280                 :            :     size_t bits, keyused;
     281                 :            :     int res;
     282                 :            : 
     283   [ +  +  +  + ]:       1876 :     if (arg == NULL || arg == Py_None) {
     284         [ -  + ]:       1757 :        if (random_seed_urandom(self) < 0) {
     285                 :          0 :             PyErr_Clear();
     286                 :            : 
     287                 :            :             /* Reading system entropy failed, fall back on the worst entropy:
     288                 :            :                use the current time and process identifier. */
     289                 :          0 :             random_seed_time_pid(self);
     290                 :            :         }
     291                 :       1757 :         return 0;
     292                 :            :     }
     293                 :            : 
     294                 :            :     /* This algorithm relies on the number being unsigned.
     295                 :            :      * So: if the arg is a PyLong, use its absolute value.
     296                 :            :      * Otherwise use its hash value, cast to unsigned.
     297                 :            :      */
     298         [ +  + ]:        119 :     if (PyLong_CheckExact(arg)) {
     299                 :        112 :         n = PyNumber_Absolute(arg);
     300         [ +  + ]:          7 :     } else if (PyLong_Check(arg)) {
     301                 :            :         /* Calling int.__abs__() prevents calling arg.__abs__(), which might
     302                 :            :            return an invalid value. See issue #31478. */
     303                 :          5 :         _randomstate *state = _randomstate_type(Py_TYPE(self));
     304                 :          5 :         n = PyObject_CallOneArg(state->Long___abs__, arg);
     305                 :            :     }
     306                 :            :     else {
     307                 :          2 :         Py_hash_t hash = PyObject_Hash(arg);
     308         [ -  + ]:          2 :         if (hash == -1)
     309                 :          0 :             goto Done;
     310                 :          2 :         n = PyLong_FromSize_t((size_t)hash);
     311                 :            :     }
     312         [ -  + ]:        119 :     if (n == NULL)
     313                 :          0 :         goto Done;
     314                 :            : 
     315                 :            :     /* Now split n into 32-bit chunks, from the right. */
     316                 :        119 :     bits = _PyLong_NumBits(n);
     317   [ -  +  -  - ]:        119 :     if (bits == (size_t)-1 && PyErr_Occurred())
     318                 :          0 :         goto Done;
     319                 :            : 
     320                 :            :     /* Figure out how many 32-bit chunks this gives us. */
     321         [ +  + ]:        119 :     keyused = bits == 0 ? 1 : (bits - 1) / 32 + 1;
     322                 :            : 
     323                 :            :     /* Convert seed to byte sequence. */
     324                 :        119 :     key = (uint32_t *)PyMem_Malloc((size_t)4 * keyused);
     325         [ -  + ]:        119 :     if (key == NULL) {
     326                 :            :         PyErr_NoMemory();
     327                 :          0 :         goto Done;
     328                 :            :     }
     329                 :        119 :     res = _PyLong_AsByteArray((PyLongObject *)n,
     330                 :            :                               (unsigned char *)key, keyused * 4,
     331                 :            :                               PY_LITTLE_ENDIAN,
     332                 :            :                               0); /* unsigned */
     333         [ -  + ]:        119 :     if (res == -1) {
     334                 :          0 :         goto Done;
     335                 :            :     }
     336                 :            : 
     337                 :            : #if PY_BIG_ENDIAN
     338                 :            :     {
     339                 :            :         size_t i, j;
     340                 :            :         /* Reverse an array. */
     341                 :            :         for (i = 0, j = keyused - 1; i < j; i++, j--) {
     342                 :            :             uint32_t tmp = key[i];
     343                 :            :             key[i] = key[j];
     344                 :            :             key[j] = tmp;
     345                 :            :         }
     346                 :            :     }
     347                 :            : #endif
     348                 :        119 :     init_by_array(self, key, keyused);
     349                 :            : 
     350                 :        119 :     result = 0;
     351                 :            : 
     352                 :        119 : Done:
     353                 :        119 :     Py_XDECREF(n);
     354                 :        119 :     PyMem_Free(key);
     355                 :        119 :     return result;
     356                 :            : }
     357                 :            : 
     358                 :            : /*[clinic input]
     359                 :            : _random.Random.seed
     360                 :            : 
     361                 :            :   self: self(type="RandomObject *")
     362                 :            :   n: object = None
     363                 :            :   /
     364                 :            : 
     365                 :            : seed([n]) -> None.
     366                 :            : 
     367                 :            : Defaults to use urandom and falls back to a combination
     368                 :            : of the current time and the process identifier.
     369                 :            : [clinic start generated code]*/
     370                 :            : 
     371                 :            : static PyObject *
     372                 :       1868 : _random_Random_seed_impl(RandomObject *self, PyObject *n)
     373                 :            : /*[clinic end generated code: output=0fad1e16ba883681 input=78d6ef0d52532a54]*/
     374                 :            : {
     375         [ -  + ]:       1868 :     if (random_seed(self, n) < 0) {
     376                 :          0 :         return NULL;
     377                 :            :     }
     378                 :       1868 :     Py_RETURN_NONE;
     379                 :            : }
     380                 :            : 
     381                 :            : /*[clinic input]
     382                 :            : _random.Random.getstate
     383                 :            : 
     384                 :            :   self: self(type="RandomObject *")
     385                 :            : 
     386                 :            : getstate() -> tuple containing the current state.
     387                 :            : [clinic start generated code]*/
     388                 :            : 
     389                 :            : static PyObject *
     390                 :         11 : _random_Random_getstate_impl(RandomObject *self)
     391                 :            : /*[clinic end generated code: output=bf6cef0c092c7180 input=b937a487928c0e89]*/
     392                 :            : {
     393                 :            :     PyObject *state;
     394                 :            :     PyObject *element;
     395                 :            :     int i;
     396                 :            : 
     397                 :         11 :     state = PyTuple_New(N+1);
     398         [ -  + ]:         11 :     if (state == NULL)
     399                 :          0 :         return NULL;
     400         [ +  + ]:       6875 :     for (i=0; i<N ; i++) {
     401                 :       6864 :         element = PyLong_FromUnsignedLong(self->state[i]);
     402         [ -  + ]:       6864 :         if (element == NULL)
     403                 :          0 :             goto Fail;
     404                 :       6864 :         PyTuple_SET_ITEM(state, i, element);
     405                 :            :     }
     406                 :         11 :     element = PyLong_FromLong((long)(self->index));
     407         [ -  + ]:         11 :     if (element == NULL)
     408                 :          0 :         goto Fail;
     409                 :         11 :     PyTuple_SET_ITEM(state, i, element);
     410                 :         11 :     return state;
     411                 :            : 
     412                 :          0 : Fail:
     413                 :          0 :     Py_DECREF(state);
     414                 :          0 :     return NULL;
     415                 :            : }
     416                 :            : 
     417                 :            : 
     418                 :            : /*[clinic input]
     419                 :            : _random.Random.setstate
     420                 :            : 
     421                 :            :   self: self(type="RandomObject *")
     422                 :            :   state: object
     423                 :            :   /
     424                 :            : 
     425                 :            : setstate(state) -> None.  Restores generator state.
     426                 :            : [clinic start generated code]*/
     427                 :            : 
     428                 :            : static PyObject *
     429                 :         17 : _random_Random_setstate(RandomObject *self, PyObject *state)
     430                 :            : /*[clinic end generated code: output=fd1c3cd0037b6681 input=b3b4efbb1bc66af8]*/
     431                 :            : {
     432                 :            :     int i;
     433                 :            :     unsigned long element;
     434                 :            :     long index;
     435                 :            :     uint32_t new_state[N];
     436                 :            : 
     437         [ -  + ]:         17 :     if (!PyTuple_Check(state)) {
     438                 :          0 :         PyErr_SetString(PyExc_TypeError,
     439                 :            :             "state vector must be a tuple");
     440                 :          0 :         return NULL;
     441                 :            :     }
     442         [ +  + ]:         17 :     if (PyTuple_Size(state) != N+1) {
     443                 :          1 :         PyErr_SetString(PyExc_ValueError,
     444                 :            :             "state vector is the wrong size");
     445                 :          1 :         return NULL;
     446                 :            :     }
     447                 :            : 
     448         [ +  + ]:      10000 :     for (i=0; i<N ; i++) {
     449                 :       9984 :         element = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(state, i));
     450   [ -  +  -  - ]:       9984 :         if (element == (unsigned long)-1 && PyErr_Occurred())
     451                 :          0 :             return NULL;
     452                 :       9984 :         new_state[i] = (uint32_t)element;
     453                 :            :     }
     454                 :            : 
     455                 :         16 :     index = PyLong_AsLong(PyTuple_GET_ITEM(state, i));
     456   [ -  +  -  - ]:         16 :     if (index == -1 && PyErr_Occurred())
     457                 :          0 :         return NULL;
     458   [ +  -  +  + ]:         16 :     if (index < 0 || index > N) {
     459                 :          2 :         PyErr_SetString(PyExc_ValueError, "invalid state");
     460                 :          2 :         return NULL;
     461                 :            :     }
     462                 :         14 :     self->index = (int)index;
     463         [ +  + ]:       8750 :     for (i = 0; i < N; i++)
     464                 :       8736 :         self->state[i] = new_state[i];
     465                 :            : 
     466                 :         14 :     Py_RETURN_NONE;
     467                 :            : }
     468                 :            : 
     469                 :            : /*[clinic input]
     470                 :            : 
     471                 :            : _random.Random.getrandbits
     472                 :            : 
     473                 :            :   self: self(type="RandomObject *")
     474                 :            :   k: int
     475                 :            :   /
     476                 :            : 
     477                 :            : getrandbits(k) -> x.  Generates an int with k random bits.
     478                 :            : [clinic start generated code]*/
     479                 :            : 
     480                 :            : static PyObject *
     481                 :    6978886 : _random_Random_getrandbits_impl(RandomObject *self, int k)
     482                 :            : /*[clinic end generated code: output=b402f82a2158887f input=8c0e6396dd176fc0]*/
     483                 :            : {
     484                 :            :     int i, words;
     485                 :            :     uint32_t r;
     486                 :            :     uint32_t *wordarray;
     487                 :            :     PyObject *result;
     488                 :            : 
     489         [ +  + ]:    6978886 :     if (k < 0) {
     490                 :          2 :         PyErr_SetString(PyExc_ValueError,
     491                 :            :                         "number of bits must be non-negative");
     492                 :          2 :         return NULL;
     493                 :            :     }
     494                 :            : 
     495         [ +  + ]:    6978884 :     if (k == 0)
     496                 :          5 :         return PyLong_FromLong(0);
     497                 :            : 
     498         [ +  + ]:    6978879 :     if (k <= 32)  /* Fast path */
     499                 :    6278335 :         return PyLong_FromUnsignedLong(genrand_uint32(self) >> (32 - k));
     500                 :            : 
     501                 :     700544 :     words = (k - 1) / 32 + 1;
     502                 :     700544 :     wordarray = (uint32_t *)PyMem_Malloc(words * 4);
     503         [ -  + ]:     700544 :     if (wordarray == NULL) {
     504                 :            :         PyErr_NoMemory();
     505                 :          0 :         return NULL;
     506                 :            :     }
     507                 :            : 
     508                 :            :     /* Fill-out bits of long integer, by 32-bit words, from least significant
     509                 :            :        to most significant. */
     510                 :            : #if PY_LITTLE_ENDIAN
     511         [ +  + ]:   15172305 :     for (i = 0; i < words; i++, k -= 32)
     512                 :            : #else
     513                 :            :     for (i = words - 1; i >= 0; i--, k -= 32)
     514                 :            : #endif
     515                 :            :     {
     516                 :   14471761 :         r = genrand_uint32(self);
     517         [ +  + ]:   14471761 :         if (k < 32)
     518                 :     622989 :             r >>= (32 - k);  /* Drop least significant bits */
     519                 :   14471761 :         wordarray[i] = r;
     520                 :            :     }
     521                 :            : 
     522                 :     700544 :     result = _PyLong_FromByteArray((unsigned char *)wordarray, words * 4,
     523                 :            :                                    PY_LITTLE_ENDIAN, 0 /* unsigned */);
     524                 :     700544 :     PyMem_Free(wordarray);
     525                 :     700544 :     return result;
     526                 :            : }
     527                 :            : 
     528                 :            : static int
     529                 :          8 : random_init(RandomObject *self, PyObject *args, PyObject *kwds)
     530                 :            : {
     531                 :          8 :     PyObject *arg = NULL;
     532                 :          8 :     _randomstate *state = _randomstate_type(Py_TYPE(self));
     533                 :            : 
     534         [ -  + ]:          8 :     if ((Py_IS_TYPE(self, (PyTypeObject *)state->Random_Type) ||
     535   [ -  -  -  + ]:          8 :          Py_TYPE(self)->tp_init == ((PyTypeObject*)state->Random_Type)->tp_init) &&
     536         [ #  # ]:          0 :         !_PyArg_NoKeywords("Random", kwds)) {
     537                 :          0 :         return -1;
     538                 :            :     }
     539                 :            : 
     540         [ -  + ]:          8 :     if (PyTuple_GET_SIZE(args) > 1) {
     541                 :          0 :         PyErr_SetString(PyExc_TypeError, "Random() requires 0 or 1 argument");
     542                 :          0 :         return -1;
     543                 :            :     }
     544                 :            : 
     545         [ +  + ]:          8 :     if (PyTuple_GET_SIZE(args) == 1)
     546                 :          1 :         arg = PyTuple_GET_ITEM(args, 0);
     547                 :            : 
     548                 :          8 :     return random_seed(self, arg);
     549                 :            : }
     550                 :            : 
     551                 :            : 
     552                 :            : static PyMethodDef random_methods[] = {
     553                 :            :     _RANDOM_RANDOM_RANDOM_METHODDEF
     554                 :            :     _RANDOM_RANDOM_SEED_METHODDEF
     555                 :            :     _RANDOM_RANDOM_GETSTATE_METHODDEF
     556                 :            :     _RANDOM_RANDOM_SETSTATE_METHODDEF
     557                 :            :     _RANDOM_RANDOM_GETRANDBITS_METHODDEF
     558                 :            :     {NULL,              NULL}           /* sentinel */
     559                 :            : };
     560                 :            : 
     561                 :            : PyDoc_STRVAR(random_doc,
     562                 :            : "Random() -> create a random number generator with its own internal state.");
     563                 :            : 
     564                 :            : static PyType_Slot Random_Type_slots[] = {
     565                 :            :     {Py_tp_doc, (void *)random_doc},
     566                 :            :     {Py_tp_methods, random_methods},
     567                 :            :     {Py_tp_new, PyType_GenericNew},
     568                 :            :     {Py_tp_init, random_init},
     569                 :            :     {Py_tp_free, PyObject_Free},
     570                 :            :     {0, 0},
     571                 :            : };
     572                 :            : 
     573                 :            : static PyType_Spec Random_Type_spec = {
     574                 :            :     "_random.Random",
     575                 :            :     sizeof(RandomObject),
     576                 :            :     0,
     577                 :            :     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
     578                 :            :     Random_Type_slots
     579                 :            : };
     580                 :            : 
     581                 :            : PyDoc_STRVAR(module_doc,
     582                 :            : "Module implements the Mersenne Twister random number generator.");
     583                 :            : 
     584                 :            : static int
     585                 :       1105 : _random_exec(PyObject *module)
     586                 :            : {
     587                 :       1105 :     _randomstate *state = get_random_state(module);
     588                 :            : 
     589                 :       1105 :     state->Random_Type = PyType_FromModuleAndSpec(
     590                 :            :         module, &Random_Type_spec, NULL);
     591         [ -  + ]:       1105 :     if (state->Random_Type == NULL) {
     592                 :          0 :         return -1;
     593                 :            :     }
     594         [ -  + ]:       1105 :     if (PyModule_AddType(module, (PyTypeObject *)state->Random_Type) < 0) {
     595                 :          0 :         return -1;
     596                 :            :     }
     597                 :            : 
     598                 :            :     /* Look up and save int.__abs__, which is needed in random_seed(). */
     599                 :       1105 :     PyObject *longval = PyLong_FromLong(0);
     600         [ -  + ]:       1105 :     if (longval == NULL) {
     601                 :          0 :         return -1;
     602                 :            :     }
     603                 :            : 
     604                 :       1105 :     PyObject *longtype = PyObject_Type(longval);
     605                 :       1105 :     Py_DECREF(longval);
     606         [ -  + ]:       1105 :     if (longtype == NULL) {
     607                 :          0 :         return -1;
     608                 :            :     }
     609                 :            : 
     610                 :       1105 :     state->Long___abs__ = PyObject_GetAttrString(longtype, "__abs__");
     611                 :       1105 :     Py_DECREF(longtype);
     612         [ -  + ]:       1105 :     if (state->Long___abs__ == NULL) {
     613                 :          0 :         return -1;
     614                 :            :     }
     615                 :       1105 :     return 0;
     616                 :            : }
     617                 :            : 
     618                 :            : static PyModuleDef_Slot _random_slots[] = {
     619                 :            :     {Py_mod_exec, _random_exec},
     620                 :            :     {0, NULL}
     621                 :            : };
     622                 :            : 
     623                 :            : static int
     624                 :      40734 : _random_traverse(PyObject *module, visitproc visit, void *arg)
     625                 :            : {
     626   [ +  -  -  + ]:      40734 :     Py_VISIT(get_random_state(module)->Random_Type);
     627                 :      40734 :     return 0;
     628                 :            : }
     629                 :            : 
     630                 :            : static int
     631                 :       2174 : _random_clear(PyObject *module)
     632                 :            : {
     633         [ +  + ]:       2174 :     Py_CLEAR(get_random_state(module)->Random_Type);
     634         [ +  + ]:       2174 :     Py_CLEAR(get_random_state(module)->Long___abs__);
     635                 :       2174 :     return 0;
     636                 :            : }
     637                 :            : 
     638                 :            : static void
     639                 :       1104 : _random_free(void *module)
     640                 :            : {
     641                 :       1104 :     _random_clear((PyObject *)module);
     642                 :       1104 : }
     643                 :            : 
     644                 :            : static struct PyModuleDef _randommodule = {
     645                 :            :     PyModuleDef_HEAD_INIT,
     646                 :            :     "_random",
     647                 :            :     module_doc,
     648                 :            :     sizeof(_randomstate),
     649                 :            :     NULL,
     650                 :            :     _random_slots,
     651                 :            :     _random_traverse,
     652                 :            :     _random_clear,
     653                 :            :     _random_free,
     654                 :            : };
     655                 :            : 
     656                 :            : PyMODINIT_FUNC
     657                 :       1105 : PyInit__random(void)
     658                 :            : {
     659                 :       1105 :     return PyModuleDef_Init(&_randommodule);
     660                 :            : }

Generated by: LCOV version 1.14