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