mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-03-03 22:52:09 +01:00
Improve generation of pseudo-random integers. (#99720, Morten Welinder
2002-12-10 Sebastian Wilhelmi <wilhelmi@ira.uka.de> * glib/grand.c (g_rand_int_range): Improve generation of pseudo-random integers. (#99720, Morten Welinder <terra@diku.dk>) * README.in, docs/reference/glib/running.sgml, docs/reference/glib/tmpl/random_numbers.sgml, docs/reference/glib/changes.sgml: Added notes about the new algorithm.
This commit is contained in:
parent
1c462ac694
commit
df9d9332f8
@ -36,12 +36,18 @@ yield equally distributed numbers.
|
|||||||
GLib changed the seeding algorithm for the pseudo-random number
|
GLib changed the seeding algorithm for the pseudo-random number
|
||||||
generator Mersenne Twister, as used by <structname>GRand</structname>
|
generator Mersenne Twister, as used by <structname>GRand</structname>
|
||||||
and <structname>GRandom</structname>. This was necessary, because some
|
and <structname>GRandom</structname>. This was necessary, because some
|
||||||
seeds would yield very bad pseudo-random streams. The original seeding
|
seeds would yield very bad pseudo-random streams. Also the
|
||||||
algorithm, as found in GLib 2.0.x, can be used instead of the new one
|
pseudo-random integers generated by
|
||||||
by setting the environment variable <envar>G_RANDOM_VERSION</envar> to
|
<function>g_rand*_int_range()</function> will have a
|
||||||
the value of '2.0'. Use the GLib-2.0 algorithm only if you have
|
slightly better equal distribution with the new version of GLib.
|
||||||
sequences of numbers generated with Glib-2.0 that you need to
|
</para>
|
||||||
reproduce exactly.
|
|
||||||
|
<para>
|
||||||
|
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.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<!-- ##### SECTION See_Also ##### -->
|
<!-- ##### SECTION See_Also ##### -->
|
||||||
|
36
glib/grand.c
36
glib/grand.c
@ -285,10 +285,9 @@ g_rand_int_range (GRand* rand, gint32 begin, gint32 end)
|
|||||||
g_return_val_if_fail (rand != NULL, begin);
|
g_return_val_if_fail (rand != NULL, begin);
|
||||||
g_return_val_if_fail (end > begin, begin);
|
g_return_val_if_fail (end > begin, begin);
|
||||||
|
|
||||||
/* All tricks doing modulo calculations do not have a perfect
|
switch (get_random_version ())
|
||||||
* distribution -> We must use the slower way through gdouble for
|
{
|
||||||
* maximal quality. */
|
case 20:
|
||||||
|
|
||||||
if (dist <= 0x10000L) /* 2^16 */
|
if (dist <= 0x10000L) /* 2^16 */
|
||||||
{
|
{
|
||||||
/* This method, which only calls g_rand_int once is only good
|
/* This method, which only calls g_rand_int once is only good
|
||||||
@ -313,6 +312,35 @@ g_rand_int_range (GRand* rand, gint32 begin, gint32 end)
|
|||||||
distribution */
|
distribution */
|
||||||
random = (gint32) g_rand_double_range (rand, 0, dist);
|
random = (gint32) g_rand_double_range (rand, 0, dist);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case 22:
|
||||||
|
if (dist == 0)
|
||||||
|
random = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* maxvalue is set to the predecessor of the greatest
|
||||||
|
* multiple of dist less or equal 2^32. */
|
||||||
|
guint32 maxvalue;
|
||||||
|
if (dist <= 0x80000000u) /* 2^31 */
|
||||||
|
{
|
||||||
|
/* maxvalue = 2^32 - 1 - (2^32 % dist) */
|
||||||
|
guint32 leftover = (0x80000000u % dist) * 2;
|
||||||
|
if (leftover >= dist) leftover -= dist;
|
||||||
|
maxvalue = 0xffffffffu - leftover;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
maxvalue = dist - 1;
|
||||||
|
|
||||||
|
do
|
||||||
|
random = g_rand_int (rand);
|
||||||
|
while (random > maxvalue);
|
||||||
|
|
||||||
|
random %= dist;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
|
||||||
return begin + random;
|
return begin + random;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user