Move GTrashStack out of gutils.[hc]
[platform/upstream/glib.git] / glib / grand.c
index 55f8970..4c0e0b4 100644 (file)
  * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GLib Team.  See the ChangeLog
  * files for a list of changes.  These files are distributed with
- * GLib at ftp://ftp.gtk.org/pub/gtk/.  
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
  */
 
-/* 
+/*
  * MT safe
  */
 
 #include <unistd.h>
 #endif
 
-#include "glib.h"
+#include "grand.h"
+
+#include "genviron.h"
+#include "gmain.h"
+#include "gmem.h"
+#include "gtestutils.h"
+#include "gthread.h"
 #include "gthreadprivate.h"
-#include "galias.h"
 
 #ifdef G_OS_WIN32
 #include <process.h>           /* For getpid() */
 #endif
 
+/**
+ * SECTION:random_numbers
+ * @title: Random Numbers
+ * @short_description: pseudo-random number generator
+ *
+ * The following functions allow you to use a portable, fast and good
+ * pseudo-random number generator (PRNG). It uses the Mersenne Twister
+ * PRNG, which was originally developed by Makoto Matsumoto and Takuji
+ * Nishimura. Further information can be found at
+ * <ulink url="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html">
+ * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html</ulink>.
+ *
+ * If you just need a random number, you simply call the
+ * <function>g_random_*</function> functions, which will create a
+ * globally used #GRand and use the according
+ * <function>g_rand_*</function> functions internally. Whenever you
+ * need a stream of reproducible random numbers, you better create a
+ * #GRand yourself and use the <function>g_rand_*</function> functions
+ * directly, which will also be slightly faster. Initializing a #GRand
+ * with a certain seed will produce exactly the same series of random
+ * numbers on all platforms. This can thus be used as a seed for e.g.
+ * games.
+ *
+ * The <function>g_rand*_range</function> functions will return high
+ * quality equally distributed random numbers, whereas for example the
+ * <literal>(g_random_int()&percnt;max)</literal> approach often
+ * doesn't yield equally distributed numbers.
+ *
+ * GLib changed the seeding algorithm for the pseudo-random number
+ * generator Mersenne Twister, as used by
+ * <structname>GRand</structname> and <structname>GRandom</structname>.
+ * This was necessary, because some seeds would yield very bad
+ * pseudo-random streams.  Also the pseudo-random integers generated by
+ * <function>g_rand*_int_range()</function> will have a slightly better
+ * equal distribution with the new version of GLib.
+ *
+ * The original seeding and generation algorithms, as found in GLib
+ * 2.0.x, can be used instead of the new ones by setting the
+ * environment variable <envar>G_RANDOM_VERSION</envar> to the value of
+ * '2.0'. Use the GLib-2.0 algorithms only if you have sequences of
+ * numbers generated with Glib-2.0 that you need to reproduce exactly.
+ **/
+
+/**
+ * GRand:
+ *
+ * The #GRand struct is an opaque data structure. It should only be
+ * accessed through the <function>g_rand_*</function> functions.
+ **/
+
 G_LOCK_DEFINE_STATIC (global_random);
 static GRand* global_random = NULL;
 
@@ -76,10 +131,10 @@ static GRand* global_random = NULL;
 static guint
 get_random_version (void)
 {
-  static gboolean initialized = FALSE;
+  static gsize initialized = FALSE;
   static guint random_version;
-  
-  if (!initialized)
+
+  if (g_once_init_enter (&initialized))
     {
       const gchar *version_string = g_getenv ("G_RANDOM_VERSION");
       if (!version_string || version_string[0] == '\000' || 
@@ -93,21 +148,12 @@ get_random_version (void)
                     version_string);
          random_version = 22;
        }
-      initialized = TRUE;
+      g_once_init_leave (&initialized, TRUE);
     }
   
   return random_version;
 }
 
-/* This is called from g_thread_init(). It's used to
- * initialize some static data in a threadsafe way.
- */
-void 
-_g_rand_thread_init (void)
-{
-  (void)get_random_version ();
-}
-
 struct _GRand
 {
   guint32 mt[N]; /* the array for the state vector  */
@@ -181,6 +227,7 @@ g_rand_new (void)
        {
          int r;
 
+         setvbuf (dev_urandom, NULL, _IONBF, 0);
          do
            {
              errno = 0;
@@ -357,6 +404,14 @@ g_rand_set_seed_array (GRand* rand, const guint32 *seed, guint seed_length)
 }
 
 /**
+ * g_rand_boolean:
+ * @rand_: a #GRand.
+ * @Returns: a random #gboolean.
+ *
+ * Returns a random #gboolean from @rand_. This corresponds to a
+ * unbiased coin toss.
+ **/
+/**
  * g_rand_int:
  * @rand_: a #GRand.
  *
@@ -523,10 +578,20 @@ g_rand_double (GRand* rand)
 gdouble 
 g_rand_double_range (GRand* rand, gdouble begin, gdouble end)
 {
-  return g_rand_double (rand) * (end - begin) + begin;
+  gdouble r;
+
+  r = g_rand_double (rand);
+
+  return r * end - (r - 1) * begin;
 }
 
 /**
+ * g_random_boolean:
+ * @Returns: a random #gboolean.
+ *
+ * Returns a random #gboolean. This corresponds to a unbiased coin toss.
+ **/
+/**
  * g_random_int:
  *
  * Return a random #guint32 equally distributed over the range
@@ -629,7 +694,3 @@ g_random_set_seed (guint32 seed)
     g_rand_set_seed (global_random, seed);
   G_UNLOCK (global_random);
 }
-
-
-#define __G_RAND_C__
-#include "galiasdef.c"