Add Since: 2.4, where due
[platform/upstream/glib.git] / glib / grand.c
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
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
41 #include <math.h>
42 #include <errno.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <sys/types.h>
46 #ifdef HAVE_UNISTD_H
47 #include <unistd.h>
48 #endif
49
50 #include "glib.h"
51 #include "gthreadinit.h"
52
53 #ifdef G_OS_WIN32
54 #include <process.h>            /* For getpid() */
55 #endif
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 
105 _g_rand_thread_init (void)
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 /**
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 /**
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 {
163   guint32 seed[4];
164   GTimeVal now;
165 #ifdef G_OS_UNIX
166   static gboolean dev_urandom_exists = TRUE;
167
168   if (dev_urandom_exists)
169     {
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
179       if (dev_urandom)
180         {
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)
191             dev_urandom_exists = FALSE;
192
193           do
194             {
195               errno = 0;
196               fclose (dev_urandom);
197             }
198           while G_UNLIKELY (errno == EINTR);
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);
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
218     }
219
220   return g_rand_new_with_seed_array (seed, 4);
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 /**
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 /**
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 /**
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 /**
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