LCOV - code coverage report
Current view: top level - glib/glib - grand.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 144 174 82.8 %
Date: 2024-04-23 05:16:05 Functions: 18 18 100.0 %
Branches: 41 70 58.6 %

           Branch data     Line data    Source code
       1                 :            : /* GLIB - Library of useful routines for C programming
       2                 :            :  * Copyright (C) 1995-1997  Peter Mattis, Spencer Kimball and Josh MacDonald
       3                 :            :  *
       4                 :            :  * SPDX-License-Identifier: LGPL-2.1-or-later
       5                 :            :  *
       6                 :            :  * This library is free software; you can redistribute it and/or
       7                 :            :  * modify it under the terms of the GNU Lesser General Public
       8                 :            :  * License as published by the Free Software Foundation; either
       9                 :            :  * version 2.1 of the License, or (at your option) any later version.
      10                 :            :  *
      11                 :            :  * This library is distributed in the hope that it will be useful,
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14                 :            :  * Lesser General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU Lesser General Public
      17                 :            :  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      18                 :            :  */
      19                 :            : 
      20                 :            : /* Originally developed and coded by Makoto Matsumoto and Takuji
      21                 :            :  * Nishimura.  Please mail <matumoto@math.keio.ac.jp>, if you're using
      22                 :            :  * code from this file in your own programs or libraries.
      23                 :            :  * Further information on the Mersenne Twister can be found at
      24                 :            :  * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
      25                 :            :  * This code was adapted to glib by Sebastian Wilhelmi.
      26                 :            :  */
      27                 :            : 
      28                 :            : /*
      29                 :            :  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
      30                 :            :  * file for a list of people on the GLib Team.  See the ChangeLog
      31                 :            :  * files for a list of changes.  These files are distributed with
      32                 :            :  * GLib at ftp://ftp.gtk.org/pub/gtk/.
      33                 :            :  */
      34                 :            : 
      35                 :            : /*
      36                 :            :  * MT safe
      37                 :            :  */
      38                 :            : 
      39                 :            : #include "config.h"
      40                 :            : #define _CRT_RAND_S
      41                 :            : 
      42                 :            : #include <math.h>
      43                 :            : #include <errno.h>
      44                 :            : #include <stdio.h>
      45                 :            : #include <string.h>
      46                 :            : #include <sys/types.h>
      47                 :            : #include "grand.h"
      48                 :            : 
      49                 :            : #include "genviron.h"
      50                 :            : #include "gmain.h"
      51                 :            : #include "gmem.h"
      52                 :            : #include "gtestutils.h"
      53                 :            : #include "gthread.h"
      54                 :            : #include "gtimer.h"
      55                 :            : 
      56                 :            : #ifdef G_OS_UNIX
      57                 :            : #include <unistd.h>
      58                 :            : #endif
      59                 :            : 
      60                 :            : #ifdef G_OS_WIN32
      61                 :            : #include <stdlib.h>
      62                 :            : #include <process.h> /* For getpid() */
      63                 :            : #endif
      64                 :            : 
      65                 :            : /**
      66                 :            :  * GRand:
      67                 :            :  *
      68                 :            :  * The GRand struct is an opaque data structure. It should only be
      69                 :            :  * accessed through the g_rand_* functions.
      70                 :            :  **/
      71                 :            : 
      72                 :            : G_LOCK_DEFINE_STATIC (global_random);
      73                 :            : 
      74                 :            : /* Period parameters */  
      75                 :            : #define N 624
      76                 :            : #define M 397
      77                 :            : #define MATRIX_A 0x9908b0df   /* constant vector a */
      78                 :            : #define UPPER_MASK 0x80000000 /* most significant w-r bits */
      79                 :            : #define LOWER_MASK 0x7fffffff /* least significant r bits */
      80                 :            : 
      81                 :            : /* Tempering parameters */   
      82                 :            : #define TEMPERING_MASK_B 0x9d2c5680
      83                 :            : #define TEMPERING_MASK_C 0xefc60000
      84                 :            : #define TEMPERING_SHIFT_U(y)  (y >> 11)
      85                 :            : #define TEMPERING_SHIFT_S(y)  (y << 7)
      86                 :            : #define TEMPERING_SHIFT_T(y)  (y << 15)
      87                 :            : #define TEMPERING_SHIFT_L(y)  (y >> 18)
      88                 :            : 
      89                 :            : static guint
      90                 :   57795835 : get_random_version (void)
      91                 :            : {
      92                 :            :   static gsize initialized = FALSE;
      93                 :            :   static guint random_version;
      94                 :            : 
      95   [ +  +  +  -  :   57795835 :   if (g_once_init_enter (&initialized))
                   +  + ]
      96                 :            :     {
      97                 :        632 :       const gchar *version_string = g_getenv ("G_RANDOM_VERSION");
      98   [ -  +  -  - ]:        632 :       if (!version_string || version_string[0] == '\000' || 
      99         [ #  # ]:          0 :           strcmp (version_string, "2.2") == 0)
     100                 :        632 :         random_version = 22;
     101         [ #  # ]:          0 :       else if (strcmp (version_string, "2.0") == 0)
     102                 :          0 :         random_version = 20;
     103                 :            :       else
     104                 :            :         {
     105                 :          0 :           g_warning ("Unknown G_RANDOM_VERSION \"%s\". Using version 2.2.",
     106                 :            :                      version_string);
     107                 :          0 :           random_version = 22;
     108                 :            :         }
     109                 :        632 :       g_once_init_leave (&initialized, TRUE);
     110                 :            :     }
     111                 :            :   
     112                 :   57795835 :   return random_version;
     113                 :            : }
     114                 :            : 
     115                 :            : struct _GRand
     116                 :            : {
     117                 :            :   guint32 mt[N]; /* the array for the state vector  */
     118                 :            :   guint mti; 
     119                 :            : };
     120                 :            : 
     121                 :            : /**
     122                 :            :  * g_rand_new_with_seed: (constructor)
     123                 :            :  * @seed: a value to initialize the random number generator
     124                 :            :  * 
     125                 :            :  * Creates a new random number generator initialized with @seed.
     126                 :            :  * 
     127                 :            :  * Returns: (transfer full): the new #GRand
     128                 :            :  **/
     129                 :            : GRand*
     130                 :      88789 : g_rand_new_with_seed (guint32 seed)
     131                 :            : {
     132                 :      88789 :   GRand *rand = g_new0 (GRand, 1);
     133                 :      88789 :   g_rand_set_seed (rand, seed);
     134                 :      88789 :   return rand;
     135                 :            : }
     136                 :            : 
     137                 :            : /**
     138                 :            :  * g_rand_new_with_seed_array: (constructor)
     139                 :            :  * @seed: an array of seeds to initialize the random number generator
     140                 :            :  * @seed_length: an array of seeds to initialize the random number
     141                 :            :  *     generator
     142                 :            :  * 
     143                 :            :  * Creates a new random number generator initialized with @seed.
     144                 :            :  * 
     145                 :            :  * Returns: (transfer full): the new #GRand
     146                 :            :  *
     147                 :            :  * Since: 2.4
     148                 :            :  */
     149                 :            : GRand*
     150                 :       8894 : g_rand_new_with_seed_array (const guint32 *seed,
     151                 :            :                             guint          seed_length)
     152                 :            : {
     153                 :       8894 :   GRand *rand = g_new0 (GRand, 1);
     154                 :       8894 :   g_rand_set_seed_array (rand, seed, seed_length);
     155                 :       8894 :   return rand;
     156                 :            : }
     157                 :            : 
     158                 :            : /**
     159                 :            :  * g_rand_new: (constructor)
     160                 :            :  * 
     161                 :            :  * Creates a new random number generator initialized with a seed taken
     162                 :            :  * either from `/dev/urandom` (if existing) or from the current time
     163                 :            :  * (as a fallback).
     164                 :            :  *
     165                 :            :  * On Windows, the seed is taken from rand_s().
     166                 :            :  * 
     167                 :            :  * Returns: (transfer full): the new #GRand
     168                 :            :  */
     169                 :            : GRand* 
     170                 :       1246 : g_rand_new (void)
     171                 :            : {
     172                 :            :   guint32 seed[4];
     173                 :            : #ifdef G_OS_UNIX
     174                 :            :   static gboolean dev_urandom_exists = TRUE;
     175                 :            : 
     176         [ +  - ]:       1246 :   if (dev_urandom_exists)
     177                 :            :     {
     178                 :            :       FILE* dev_urandom;
     179                 :            : 
     180                 :            :       do
     181                 :            :         {
     182                 :       1246 :           dev_urandom = fopen ("/dev/urandom", "rbe");
     183                 :            :         }
     184   [ -  +  -  - ]:       1246 :       while G_UNLIKELY (dev_urandom == NULL && errno == EINTR);
     185                 :            : 
     186         [ +  - ]:       1246 :       if (dev_urandom)
     187                 :            :         {
     188                 :            :           int r;
     189                 :            : 
     190                 :       1246 :           setvbuf (dev_urandom, NULL, _IONBF, 0);
     191                 :            :           do
     192                 :            :             {
     193                 :       1246 :               errno = 0;
     194                 :       1246 :               r = fread (seed, sizeof (seed), 1, dev_urandom);
     195                 :            :             }
     196         [ -  + ]:       1246 :           while G_UNLIKELY (errno == EINTR);
     197                 :            : 
     198         [ -  + ]:       1246 :           if (r != 1)
     199                 :          0 :             dev_urandom_exists = FALSE;
     200                 :            : 
     201                 :       1246 :           fclose (dev_urandom);
     202                 :            :         }       
     203                 :            :       else
     204                 :          0 :         dev_urandom_exists = FALSE;
     205                 :            :     }
     206                 :            : 
     207         [ -  + ]:       1246 :   if (!dev_urandom_exists)
     208                 :            :     {
     209                 :          0 :       gint64 now_us = g_get_real_time ();
     210                 :          0 :       seed[0] = now_us / G_USEC_PER_SEC;
     211                 :          0 :       seed[1] = now_us % G_USEC_PER_SEC;
     212                 :          0 :       seed[2] = getpid ();
     213                 :          0 :       seed[3] = getppid ();
     214                 :            :     }
     215                 :            : #else /* G_OS_WIN32 */
     216                 :            :   /* rand_s() is only available since Visual Studio 2005 and
     217                 :            :    * MinGW-w64 has a wrapper that will emulate rand_s() if it's not in msvcrt
     218                 :            :    */
     219                 :            : #if (defined(_MSC_VER) && _MSC_VER >= 1400) || defined(__MINGW64_VERSION_MAJOR)
     220                 :            :   gsize i;
     221                 :            : 
     222                 :            :   for (i = 0; i < G_N_ELEMENTS (seed); i++)
     223                 :            :     rand_s (&seed[i]);
     224                 :            : #else
     225                 :            : #warning Using insecure seed for random number generation because of missing rand_s() in Windows XP
     226                 :            :   GTimeVal now;
     227                 :            : 
     228                 :            :   g_get_current_time (&now);
     229                 :            :   seed[0] = now.tv_sec;
     230                 :            :   seed[1] = now.tv_usec;
     231                 :            :   seed[2] = getpid ();
     232                 :            :   seed[3] = 0;
     233                 :            : #endif
     234                 :            : 
     235                 :            : #endif
     236                 :            : 
     237                 :       1246 :   return g_rand_new_with_seed_array (seed, 4);
     238                 :            : }
     239                 :            : 
     240                 :            : /**
     241                 :            :  * g_rand_free:
     242                 :            :  * @rand_: a #GRand
     243                 :            :  *
     244                 :            :  * Frees the memory allocated for the #GRand.
     245                 :            :  */
     246                 :            : void
     247                 :      96968 : g_rand_free (GRand *rand)
     248                 :            : {
     249                 :      96968 :   g_return_if_fail (rand != NULL);
     250                 :            : 
     251                 :      96968 :   g_free (rand);
     252                 :            : }
     253                 :            : 
     254                 :            : /**
     255                 :            :  * g_rand_copy:
     256                 :            :  * @rand_: a #GRand
     257                 :            :  *
     258                 :            :  * Copies a #GRand into a new one with the same exact state as before.
     259                 :            :  * This way you can take a snapshot of the random number generator for
     260                 :            :  * replaying later.
     261                 :            :  *
     262                 :            :  * Returns: (transfer full): the new #GRand
     263                 :            :  *
     264                 :            :  * Since: 2.4
     265                 :            :  */
     266                 :            : GRand*
     267                 :          2 : g_rand_copy (GRand *rand)
     268                 :            : {
     269                 :            :   GRand* new_rand;
     270                 :            : 
     271                 :          2 :   g_return_val_if_fail (rand != NULL, NULL);
     272                 :            : 
     273                 :          2 :   new_rand = g_new0 (GRand, 1);
     274                 :          2 :   memcpy (new_rand, rand, sizeof (GRand));
     275                 :            : 
     276                 :          2 :   return new_rand;
     277                 :            : }
     278                 :            : 
     279                 :            : /**
     280                 :            :  * g_rand_set_seed:
     281                 :            :  * @rand_: a #GRand
     282                 :            :  * @seed: a value to reinitialize the random number generator
     283                 :            :  *
     284                 :            :  * Sets the seed for the random number generator #GRand to @seed.
     285                 :            :  */
     286                 :            : void
     287                 :     347697 : g_rand_set_seed (GRand   *rand,
     288                 :            :                  guint32  seed)
     289                 :            : {
     290                 :     347697 :   g_return_if_fail (rand != NULL);
     291                 :            : 
     292      [ -  +  - ]:     347697 :   switch (get_random_version ())
     293                 :            :     {
     294                 :          0 :     case 20:
     295                 :            :       /* setting initial seeds to mt[N] using         */
     296                 :            :       /* the generator Line 25 of Table 1 in          */
     297                 :            :       /* [KNUTH 1981, The Art of Computer Programming */
     298                 :            :       /*    Vol. 2 (2nd Ed.), pp102]                  */
     299                 :            :       
     300         [ #  # ]:          0 :       if (seed == 0) /* This would make the PRNG produce only zeros */
     301                 :          0 :         seed = 0x6b842128; /* Just set it to another number */
     302                 :            :       
     303                 :          0 :       rand->mt[0]= seed;
     304         [ #  # ]:          0 :       for (rand->mti=1; rand->mti<N; rand->mti++)
     305                 :          0 :         rand->mt[rand->mti] = (69069 * rand->mt[rand->mti-1]);
     306                 :            :       
     307                 :          0 :       break;
     308                 :     347697 :     case 22:
     309                 :            :       /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
     310                 :            :       /* In the previous version (see above), MSBs of the    */
     311                 :            :       /* seed affect only MSBs of the array mt[].            */
     312                 :            :       
     313                 :     347697 :       rand->mt[0]= seed;
     314         [ +  + ]:  216962928 :       for (rand->mti=1; rand->mti<N; rand->mti++)
     315                 :  216615231 :         rand->mt[rand->mti] = 1812433253UL * 
     316                 :  216615231 :           (rand->mt[rand->mti-1] ^ (rand->mt[rand->mti-1] >> 30)) + rand->mti; 
     317                 :     347697 :       break;
     318                 :          0 :     default:
     319                 :            :       g_assert_not_reached ();
     320                 :            :     }
     321                 :            : }
     322                 :            : 
     323                 :            : /**
     324                 :            :  * g_rand_set_seed_array:
     325                 :            :  * @rand_: a #GRand
     326                 :            :  * @seed: array to initialize with
     327                 :            :  * @seed_length: length of array
     328                 :            :  *
     329                 :            :  * Initializes the random number generator by an array of longs.
     330                 :            :  * Array can be of arbitrary size, though only the first 624 values
     331                 :            :  * are taken.  This function is useful if you have many low entropy
     332                 :            :  * seeds, or if you require more then 32 bits of actual entropy for
     333                 :            :  * your application.
     334                 :            :  *
     335                 :            :  * Since: 2.4
     336                 :            :  */
     337                 :            : void
     338                 :       8895 : g_rand_set_seed_array (GRand         *rand,
     339                 :            :                        const guint32 *seed,
     340                 :            :                        guint          seed_length)
     341                 :            : {
     342                 :            :   guint i, j, k;
     343                 :            : 
     344                 :       8895 :   g_return_if_fail (rand != NULL);
     345                 :       8895 :   g_return_if_fail (seed_length >= 1);
     346                 :            : 
     347                 :       8895 :   g_rand_set_seed (rand, 19650218UL);
     348                 :            : 
     349                 :       8895 :   i=1; j=0;
     350                 :       8895 :   k = (N>seed_length ? N : seed_length);
     351         [ +  + ]:    5559375 :   for (; k; k--)
     352                 :            :     {
     353                 :    5550480 :       rand->mt[i] = (rand->mt[i] ^
     354                 :    5550480 :                      ((rand->mt[i-1] ^ (rand->mt[i-1] >> 30)) * 1664525UL))
     355                 :    5550480 :               + seed[j] + j; /* non linear */
     356                 :    5550480 :       rand->mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
     357                 :    5550480 :       i++; j++;
     358         [ +  + ]:    5550480 :       if (i>=N)
     359                 :            :         {
     360                 :       8895 :           rand->mt[0] = rand->mt[N-1];
     361                 :       8895 :           i=1;
     362                 :            :         }
     363         [ +  + ]:    5550480 :       if (j>=seed_length)
     364                 :    1388140 :         j=0;
     365                 :            :     }
     366         [ +  + ]:    5550480 :   for (k=N-1; k; k--)
     367                 :            :     {
     368                 :    5541585 :       rand->mt[i] = (rand->mt[i] ^
     369                 :    5541585 :                      ((rand->mt[i-1] ^ (rand->mt[i-1] >> 30)) * 1566083941UL))
     370                 :    5541585 :               - i; /* non linear */
     371                 :    5541585 :       rand->mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
     372                 :    5541585 :       i++;
     373         [ +  + ]:    5541585 :       if (i>=N)
     374                 :            :         {
     375                 :       8895 :           rand->mt[0] = rand->mt[N-1];
     376                 :       8895 :           i=1;
     377                 :            :         }
     378                 :            :     }
     379                 :            : 
     380                 :       8895 :   rand->mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ 
     381                 :            : }
     382                 :            : 
     383                 :            : /**
     384                 :            :  * g_rand_boolean:
     385                 :            :  * @rand_: a #GRand
     386                 :            :  *
     387                 :            :  * Returns a random #gboolean from @rand_.
     388                 :            :  * This corresponds to an unbiased coin toss.
     389                 :            :  *
     390                 :            :  * Returns: a random #gboolean
     391                 :            :  */
     392                 :            : /**
     393                 :            :  * g_rand_int:
     394                 :            :  * @rand_: a #GRand
     395                 :            :  *
     396                 :            :  * Returns the next random #guint32 from @rand_ equally distributed over
     397                 :            :  * the range [0..2^32-1].
     398                 :            :  *
     399                 :            :  * Returns: a random number
     400                 :            :  */
     401                 :            : guint32
     402                 :  146207642 : g_rand_int (GRand *rand)
     403                 :            : {
     404                 :            :   guint32 y;
     405                 :            :   static const guint32 mag01[2]={0x0, MATRIX_A};
     406                 :            :   /* mag01[x] = x * MATRIX_A  for x=0,1 */
     407                 :            : 
     408                 :  146207642 :   g_return_val_if_fail (rand != NULL, 0);
     409                 :            : 
     410         [ +  + ]:  146207642 :   if (rand->mti >= N) { /* generate N words at one time */
     411                 :            :     int kk;
     412                 :            :     
     413         [ +  + ]:  123148956 :     for (kk = 0; kk < N - M; kk++) {
     414                 :  122608829 :       y = (rand->mt[kk]&UPPER_MASK)|(rand->mt[kk+1]&LOWER_MASK);
     415                 :  122608829 :       rand->mt[kk] = rand->mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1];
     416                 :            :     }
     417         [ +  + ]:  214430419 :     for (; kk < N - 1; kk++) {
     418                 :  213890292 :       y = (rand->mt[kk]&UPPER_MASK)|(rand->mt[kk+1]&LOWER_MASK);
     419                 :  213890292 :       rand->mt[kk] = rand->mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1];
     420                 :            :     }
     421                 :     540127 :     y = (rand->mt[N-1]&UPPER_MASK)|(rand->mt[0]&LOWER_MASK);
     422                 :     540127 :     rand->mt[N-1] = rand->mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1];
     423                 :            :     
     424                 :     540127 :     rand->mti = 0;
     425                 :            :   }
     426                 :            :   
     427                 :  146207642 :   y = rand->mt[rand->mti++];
     428                 :  146207642 :   y ^= TEMPERING_SHIFT_U(y);
     429                 :  146207642 :   y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
     430                 :  146207642 :   y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
     431                 :  146207642 :   y ^= TEMPERING_SHIFT_L(y);
     432                 :            :   
     433                 :  146207642 :   return y; 
     434                 :            : }
     435                 :            : 
     436                 :            : /* transform [0..2^32] -> [0..1] */
     437                 :            : #define G_RAND_DOUBLE_TRANSFORM 2.3283064365386962890625e-10
     438                 :            : 
     439                 :            : /**
     440                 :            :  * g_rand_int_range:
     441                 :            :  * @rand_: a #GRand
     442                 :            :  * @begin: lower closed bound of the interval
     443                 :            :  * @end: upper open bound of the interval
     444                 :            :  *
     445                 :            :  * Returns the next random #gint32 from @rand_ equally distributed over
     446                 :            :  * the range [@begin..@end-1].
     447                 :            :  *
     448                 :            :  * Returns: a random number
     449                 :            :  */
     450                 :            : gint32 
     451                 :   57448138 : g_rand_int_range (GRand  *rand,
     452                 :            :                   gint32  begin,
     453                 :            :                   gint32  end)
     454                 :            : {
     455                 :   57448138 :   guint32 dist = end - begin;
     456                 :   57448138 :   guint32 random = 0;
     457                 :            : 
     458                 :   57448138 :   g_return_val_if_fail (rand != NULL, begin);
     459                 :   57448138 :   g_return_val_if_fail (end > begin, begin);
     460                 :            : 
     461      [ -  +  - ]:   57448138 :   switch (get_random_version ())
     462                 :            :     {
     463                 :          0 :     case 20:
     464         [ #  # ]:          0 :       if (dist <= 0x10000L) /* 2^16 */
     465                 :            :         {
     466                 :            :           /* This method, which only calls g_rand_int once is only good
     467                 :            :            * for (end - begin) <= 2^16, because we only have 32 bits set
     468                 :            :            * from the one call to g_rand_int ().
     469                 :            :            *
     470                 :            :            * We are using (trans + trans * trans), because g_rand_int only
     471                 :            :            * covers [0..2^32-1] and thus g_rand_int * trans only covers
     472                 :            :            * [0..1-2^-32], but the biggest double < 1 is 1-2^-52. 
     473                 :            :            */
     474                 :            :           
     475                 :          0 :           gdouble double_rand = g_rand_int (rand) * 
     476                 :            :             (G_RAND_DOUBLE_TRANSFORM +
     477                 :            :              G_RAND_DOUBLE_TRANSFORM * G_RAND_DOUBLE_TRANSFORM);
     478                 :            :           
     479                 :          0 :           random = (gint32) (double_rand * dist);
     480                 :            :         }
     481                 :            :       else
     482                 :            :         {
     483                 :            :           /* Now we use g_rand_double_range (), which will set 52 bits
     484                 :            :            * for us, so that it is safe to round and still get a decent
     485                 :            :            * distribution
     486                 :            :            */
     487                 :          0 :           random = (gint32) g_rand_double_range (rand, 0, dist);
     488                 :            :         }
     489                 :          0 :       break;
     490                 :   57448138 :     case 22:
     491         [ -  + ]:   57448138 :       if (dist == 0)
     492                 :          0 :         random = 0;
     493                 :            :       else 
     494                 :            :         {
     495                 :            :           /* maxvalue is set to the predecessor of the greatest
     496                 :            :            * multiple of dist less or equal 2^32.
     497                 :            :            */
     498                 :            :           guint32 maxvalue;
     499         [ +  - ]:   57448138 :           if (dist <= 0x80000000u) /* 2^31 */
     500                 :            :             {
     501                 :            :               /* maxvalue = 2^32 - 1 - (2^32 % dist) */
     502                 :   57448138 :               guint32 leftover = (0x80000000u % dist) * 2;
     503         [ +  + ]:   57448138 :               if (leftover >= dist) leftover -= dist;
     504                 :   57448138 :               maxvalue = 0xffffffffu - leftover;
     505                 :            :             }
     506                 :            :           else
     507                 :          0 :             maxvalue = dist - 1;
     508                 :            :           
     509                 :            :           do
     510                 :   57448145 :             random = g_rand_int (rand);
     511         [ +  + ]:   57448145 :           while (random > maxvalue);
     512                 :            :           
     513                 :   57448138 :           random %= dist;
     514                 :            :         }
     515                 :   57448138 :       break;
     516                 :          0 :     default:
     517                 :            :       g_assert_not_reached ();
     518                 :            :     }      
     519                 :            :  
     520                 :   57448138 :   return begin + random;
     521                 :            : }
     522                 :            : 
     523                 :            : /**
     524                 :            :  * g_rand_double:
     525                 :            :  * @rand_: a #GRand
     526                 :            :  *
     527                 :            :  * Returns the next random #gdouble from @rand_ equally distributed over
     528                 :            :  * the range [0..1).
     529                 :            :  *
     530                 :            :  * Returns: a random number
     531                 :            :  */
     532                 :            : gdouble 
     533                 :   15013104 : g_rand_double (GRand *rand)
     534                 :            : {    
     535                 :            :   /* We set all 52 bits after the point for this, not only the first
     536                 :            :      32. That's why we need two calls to g_rand_int */
     537                 :   15013104 :   gdouble retval = g_rand_int (rand) * G_RAND_DOUBLE_TRANSFORM;
     538                 :   15013104 :   retval = (retval + g_rand_int (rand)) * G_RAND_DOUBLE_TRANSFORM;
     539                 :            : 
     540                 :            :   /* The following might happen due to very bad rounding luck, but
     541                 :            :    * actually this should be more than rare, we just try again then */
     542         [ -  + ]:   15013104 :   if (retval >= 1.0) 
     543                 :          0 :     return g_rand_double (rand);
     544                 :            : 
     545                 :   15013104 :   return retval;
     546                 :            : }
     547                 :            : 
     548                 :            : /**
     549                 :            :  * g_rand_double_range:
     550                 :            :  * @rand_: a #GRand
     551                 :            :  * @begin: lower closed bound of the interval
     552                 :            :  * @end: upper open bound of the interval
     553                 :            :  *
     554                 :            :  * Returns the next random #gdouble from @rand_ equally distributed over
     555                 :            :  * the range [@begin..@end).
     556                 :            :  *
     557                 :            :  * Returns: a random number
     558                 :            :  */
     559                 :            : gdouble 
     560                 :   14722347 : g_rand_double_range (GRand   *rand,
     561                 :            :                      gdouble  begin,
     562                 :            :                      gdouble  end)
     563                 :            : {
     564                 :            :   gdouble r;
     565                 :            : 
     566                 :   14722347 :   r = g_rand_double (rand);
     567                 :            : 
     568                 :   14722347 :   return r * end - (r - 1) * begin;
     569                 :            : }
     570                 :            : 
     571                 :            : static GRand *
     572                 :   30499400 : get_global_random (void)
     573                 :            : {
     574                 :            :   static GRand *global_random;
     575                 :            : 
     576                 :            :   /* called while locked */
     577         [ +  + ]:   30499400 :   if (!global_random)
     578                 :        632 :     global_random = g_rand_new ();
     579                 :            : 
     580                 :   30499400 :   return global_random;
     581                 :            : }
     582                 :            : 
     583                 :            : /**
     584                 :            :  * g_random_boolean:
     585                 :            :  *
     586                 :            :  * Returns a random #gboolean.
     587                 :            :  * This corresponds to an unbiased coin toss.
     588                 :            :  *
     589                 :            :  * Returns: a random #gboolean
     590                 :            :  */
     591                 :            : /**
     592                 :            :  * g_random_int:
     593                 :            :  *
     594                 :            :  * Return a random #guint32 equally distributed over the range
     595                 :            :  * [0..2^32-1].
     596                 :            :  *
     597                 :            :  * Returns: a random number
     598                 :            :  */
     599                 :            : guint32
     600                 :   20798517 : g_random_int (void)
     601                 :            : {
     602                 :            :   guint32 result;
     603                 :   20798517 :   G_LOCK (global_random);
     604                 :   20798517 :   result = g_rand_int (get_global_random ());
     605                 :   20798517 :   G_UNLOCK (global_random);
     606                 :   20798517 :   return result;
     607                 :            : }
     608                 :            : 
     609                 :            : /**
     610                 :            :  * g_random_int_range:
     611                 :            :  * @begin: lower closed bound of the interval
     612                 :            :  * @end: upper open bound of the interval
     613                 :            :  *
     614                 :            :  * Returns a random #gint32 equally distributed over the range
     615                 :            :  * [@begin..@end-1].
     616                 :            :  *
     617                 :            :  * Returns: a random number
     618                 :            :  */
     619                 :            : gint32 
     620                 :    9194030 : g_random_int_range (gint32 begin,
     621                 :            :                     gint32 end)
     622                 :            : {
     623                 :            :   gint32 result;
     624                 :    9194030 :   G_LOCK (global_random);
     625                 :    9194030 :   result = g_rand_int_range (get_global_random (), begin, end);
     626                 :    9194030 :   G_UNLOCK (global_random);
     627                 :    9194030 :   return result;
     628                 :            : }
     629                 :            : 
     630                 :            : /**
     631                 :            :  * g_random_double:
     632                 :            :  *
     633                 :            :  * Returns a random #gdouble equally distributed over the range [0..1).
     634                 :            :  *
     635                 :            :  * Returns: a random number
     636                 :            :  */
     637                 :            : gdouble 
     638                 :     156841 : g_random_double (void)
     639                 :            : {
     640                 :            :   double result;
     641                 :     156841 :   G_LOCK (global_random);
     642                 :     156841 :   result = g_rand_double (get_global_random ());
     643                 :     156841 :   G_UNLOCK (global_random);
     644                 :     156841 :   return result;
     645                 :            : }
     646                 :            : 
     647                 :            : /**
     648                 :            :  * g_random_double_range:
     649                 :            :  * @begin: lower closed bound of the interval
     650                 :            :  * @end: upper open bound of the interval
     651                 :            :  *
     652                 :            :  * Returns a random #gdouble equally distributed over the range
     653                 :            :  * [@begin..@end).
     654                 :            :  *
     655                 :            :  * Returns: a random number
     656                 :            :  */
     657                 :            : gdouble 
     658                 :     100000 : g_random_double_range (gdouble begin,
     659                 :            :                        gdouble end)
     660                 :            : {
     661                 :            :   double result;
     662                 :     100000 :   G_LOCK (global_random);
     663                 :     100000 :   result = g_rand_double_range (get_global_random (), begin, end);
     664                 :     100000 :   G_UNLOCK (global_random);
     665                 :     100000 :   return result;
     666                 :            : }
     667                 :            : 
     668                 :            : /**
     669                 :            :  * g_random_set_seed:
     670                 :            :  * @seed: a value to reinitialize the global random number generator
     671                 :            :  * 
     672                 :            :  * Sets the seed for the global random number generator, which is used
     673                 :            :  * by the g_random_* functions, to @seed.
     674                 :            :  */
     675                 :            : void
     676                 :     250012 : g_random_set_seed (guint32 seed)
     677                 :            : {
     678                 :     250012 :   G_LOCK (global_random);
     679                 :     250012 :   g_rand_set_seed (get_global_random (), seed);
     680                 :     250012 :   G_UNLOCK (global_random);
     681                 :     250012 : }

Generated by: LCOV version 1.14