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