* code from this file in your own programs or libraries.
* Further information on the Mersenne Twister can be found at
* http://www.math.keio.ac.jp/~matumoto/emt.html
+ * This code was adapted to glib by Sebastian Wilhelmi <wilhelmi@ira.uka.de>.
*/
/*
* GLib at ftp://ftp.gtk.org/pub/gtk/.
*/
+/*
+ * MT safe
+ */
+
#include <glib.h>
#include <math.h>
#include <stdio.h>
{
guint32 mt[N]; /* the array for the state vector */
guint mti;
- gboolean have_next_normal;
- gdouble next_normal;
};
GRand*
}
GRand*
-g_rand_new ()
+g_rand_new (void)
{
- guint32 seed = 0;
+ guint32 seed;
GTimeVal now;
- FILE* dev_random = fopen("/dev/random", "rb");
-
- if (dev_random)
+ static gboolean dev_urandom_exists = TRUE;
+
+ if (dev_urandom_exists)
{
- if (fread (&seed, sizeof (seed), 1, dev_random) != 1)
- seed = 0;
- fclose (dev_random);
+ FILE* dev_urandom = fopen("/dev/urandom", "rb");
+ if (dev_urandom)
+ {
+ if (fread (&seed, sizeof (seed), 1, dev_urandom) != 1)
+ seed = 0;
+ else
+ dev_urandom_exists = FALSE;
+ fclose (dev_urandom);
+ }
+ else
+ dev_urandom_exists = FALSE;
+ }
+ if (!dev_urandom_exists)
+ {
+ g_get_current_time (&now);
+ seed = now.tv_sec ^ now.tv_usec;
}
-
- /* Using /dev/random alone makes the seed computable for the
- outside. This might pose security problems somewhere. This should
- yield better values */
-
- g_get_current_time (&now);
- seed ^= now.tv_sec ^ now.tv_usec;
return g_rand_new_with_seed (seed);
}
void
g_rand_free (GRand* rand)
{
- g_return_if_fail (rand);
+ g_return_if_fail (rand != NULL);
g_free (rand);
}
void
g_rand_set_seed (GRand* rand, guint32 seed)
{
- g_return_if_fail (rand);
+ g_return_if_fail (rand != NULL);
/* setting initial seeds to mt[N] using */
/* the generator Line 25 of Table 1 in */
/* [KNUTH 1981, The Art of Computer Programming */
/* Vol. 2 (2nd Ed.), pp102] */
+
+ if (seed == 0) /* This would make the PRNG procude only zeros */
+ seed = 0x6b842128; /* Just set it to another number */
+
rand->mt[0]= seed & 0xffffffff;
for (rand->mti=1; rand->mti<N; rand->mti++)
rand->mt[rand->mti] = (69069 * rand->mt[rand->mti-1]) & 0xffffffff;
-
- rand->have_next_normal = FALSE;
}
guint32
static const guint32 mag01[2]={0x0, MATRIX_A};
/* mag01[x] = x * MATRIX_A for x=0,1 */
- g_return_val_if_fail (rand, 0);
+ g_return_val_if_fail (rand != NULL, 0);
if (rand->mti >= N) { /* generate N words at one time */
int kk;
guint32 dist = max - min;
guint32 random;
- g_return_val_if_fail (rand, min);
+ g_return_val_if_fail (rand != NULL, min);
g_return_val_if_fail (max > min, min);
if (dist <= 0x10000L) /* 2^16 */
return g_rand_int (rand) * ((max - min) * G_RAND_DOUBLE_TRANSFORM) + min;
}
-
-#if WE_REALLY_WANT_HAVE_MATH_LIB_LINKED
-gdouble
-g_rand_normal (GRand* rand, gdouble mean, gdouble standard_deviation)
-{
- /* For a description of the used algorithm see Knuth: "The Art of
- Computer Programming", Vol.2, Second Edition, Page 117: Polar
- method for normal deviates due to Box, Muller, Marsaglia */
- gdouble normal;
- g_return_val_if_fail (rand, 0);
-
- if (rand->have_next_normal)
- {
- rand->have_next_normal = FALSE;
- normal = rand->next_normal;
- }
- else
- {
- gdouble u1;
- gdouble u2 = g_rand_double_range (rand, -1, 1);
- gdouble s, f;
- do
- {
- u1 = u2;
- u2 = g_rand_double_range (rand, -1, 1);
- s = u1 * u1 + u2 * u2;
- } while (s >= 1.0);
- f = sqrt (-2 * log (s) / s);
- normal = u1 * f;
- rand->next_normal = u2 * f;
- rand->have_next_normal = TRUE;
- }
- return mean + normal * standard_deviation;
-}
-#endif
-
guint32
g_random_int (void)
{
return result;
}
-#if WE_REALLY_WANT_HAVE_MATH_LIB_LINKED
-gdouble
-g_random_normal (gdouble mean, gdouble standard_deviation)
-{
- double result;
- G_LOCK (global_random);
- if (!global_random)
- global_random = g_rand_new ();
-
- result = g_rand_normal (global_random, mean, standard_deviation);
- G_UNLOCK (global_random);
- return result;
-}
-#endif
-
void
g_random_set_seed (guint32 seed)
{