Updated G_RAND_DOUBLE_TRANSFORM to be more accurate. Redid g_rand_double()

2000-12-19  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>

	* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
	accurate. Redid g_rand_double() such that it returns 52 bits after
	the point instead of 32 as before. That OTOH requires calling
	g_rand_int() twice. Overhauled g_rand_int_range(), which is easier
	now thanks to the new precision of g_rand_double(). Thanks to
	Sverre Johansen <sj@ifi.uio.no> for the hint.

	* grand.h: Added g_rand_boolean() and g_random_boolean()
	macros. While they could be omitted due to extreme simplicity,
	they make intention clearer in code and are therefore good to have.

	* grand.c, grand.h: Renamed all 'min' and 'max' parameters to'
	begin' and 'end' resp. to avoid making people think, that 'max' is
	included in the interval. 'end' now isn't, whereas 'begin'
	is. That's similar to the use in the STL.

	* glib/glib-sections.txt: Added g_rand_boolean and
	g_random_boolean macros.

	* glib/tmpl/random_numbers.sgml: Updated.
This commit is contained in:
Sebastian Wilhelmi 2000-12-19 15:57:53 +00:00 committed by Sebastian Wilhelmi
parent 2fb47703e2
commit 32241715f4
15 changed files with 317 additions and 158 deletions

View File

@ -1,5 +1,21 @@
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
accurate. Redid g_rand_double() such that it returns 52 bits after
the point instead of 32 as before. That OTOH requires calling
g_rand_int() twice. Overhauled g_rand_int_range(), which is easier
now thanks to the new precision of g_rand_double(). Thanks to
Sverre Johansen <sj@ifi.uio.no> for the hint.
* grand.h: Added g_rand_boolean() and g_random_boolean()
macros. While they could be omitted due to extreme simplicity,
they make intention clearer in code and are therefore good to have.
* grand.c, grand.h: Renamed all 'min' and 'max' parameters to'
begin' and 'end' resp. to avoid making people think, that 'max' is
included in the interval. 'end' now isn't, whereas 'begin'
is. That's similar to the use in the STL.
* gslist.c, glist.c: Ok, I'm a moron. When I originally
implemented ENABLE_GC_FRIENDLY, I forgot to include config.h into
the affected files. Now that Alex did that for those two,

View File

@ -1,5 +1,21 @@
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
accurate. Redid g_rand_double() such that it returns 52 bits after
the point instead of 32 as before. That OTOH requires calling
g_rand_int() twice. Overhauled g_rand_int_range(), which is easier
now thanks to the new precision of g_rand_double(). Thanks to
Sverre Johansen <sj@ifi.uio.no> for the hint.
* grand.h: Added g_rand_boolean() and g_random_boolean()
macros. While they could be omitted due to extreme simplicity,
they make intention clearer in code and are therefore good to have.
* grand.c, grand.h: Renamed all 'min' and 'max' parameters to'
begin' and 'end' resp. to avoid making people think, that 'max' is
included in the interval. 'end' now isn't, whereas 'begin'
is. That's similar to the use in the STL.
* gslist.c, glist.c: Ok, I'm a moron. When I originally
implemented ENABLE_GC_FRIENDLY, I forgot to include config.h into
the affected files. Now that Alex did that for those two,

View File

@ -1,5 +1,21 @@
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
accurate. Redid g_rand_double() such that it returns 52 bits after
the point instead of 32 as before. That OTOH requires calling
g_rand_int() twice. Overhauled g_rand_int_range(), which is easier
now thanks to the new precision of g_rand_double(). Thanks to
Sverre Johansen <sj@ifi.uio.no> for the hint.
* grand.h: Added g_rand_boolean() and g_random_boolean()
macros. While they could be omitted due to extreme simplicity,
they make intention clearer in code and are therefore good to have.
* grand.c, grand.h: Renamed all 'min' and 'max' parameters to'
begin' and 'end' resp. to avoid making people think, that 'max' is
included in the interval. 'end' now isn't, whereas 'begin'
is. That's similar to the use in the STL.
* gslist.c, glist.c: Ok, I'm a moron. When I originally
implemented ENABLE_GC_FRIENDLY, I forgot to include config.h into
the affected files. Now that Alex did that for those two,

View File

@ -1,5 +1,21 @@
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
accurate. Redid g_rand_double() such that it returns 52 bits after
the point instead of 32 as before. That OTOH requires calling
g_rand_int() twice. Overhauled g_rand_int_range(), which is easier
now thanks to the new precision of g_rand_double(). Thanks to
Sverre Johansen <sj@ifi.uio.no> for the hint.
* grand.h: Added g_rand_boolean() and g_random_boolean()
macros. While they could be omitted due to extreme simplicity,
they make intention clearer in code and are therefore good to have.
* grand.c, grand.h: Renamed all 'min' and 'max' parameters to'
begin' and 'end' resp. to avoid making people think, that 'max' is
included in the interval. 'end' now isn't, whereas 'begin'
is. That's similar to the use in the STL.
* gslist.c, glist.c: Ok, I'm a moron. When I originally
implemented ENABLE_GC_FRIENDLY, I forgot to include config.h into
the affected files. Now that Alex did that for those two,

View File

@ -1,5 +1,21 @@
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
accurate. Redid g_rand_double() such that it returns 52 bits after
the point instead of 32 as before. That OTOH requires calling
g_rand_int() twice. Overhauled g_rand_int_range(), which is easier
now thanks to the new precision of g_rand_double(). Thanks to
Sverre Johansen <sj@ifi.uio.no> for the hint.
* grand.h: Added g_rand_boolean() and g_random_boolean()
macros. While they could be omitted due to extreme simplicity,
they make intention clearer in code and are therefore good to have.
* grand.c, grand.h: Renamed all 'min' and 'max' parameters to'
begin' and 'end' resp. to avoid making people think, that 'max' is
included in the interval. 'end' now isn't, whereas 'begin'
is. That's similar to the use in the STL.
* gslist.c, glist.c: Ok, I'm a moron. When I originally
implemented ENABLE_GC_FRIENDLY, I forgot to include config.h into
the affected files. Now that Alex did that for those two,

View File

@ -1,5 +1,21 @@
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
accurate. Redid g_rand_double() such that it returns 52 bits after
the point instead of 32 as before. That OTOH requires calling
g_rand_int() twice. Overhauled g_rand_int_range(), which is easier
now thanks to the new precision of g_rand_double(). Thanks to
Sverre Johansen <sj@ifi.uio.no> for the hint.
* grand.h: Added g_rand_boolean() and g_random_boolean()
macros. While they could be omitted due to extreme simplicity,
they make intention clearer in code and are therefore good to have.
* grand.c, grand.h: Renamed all 'min' and 'max' parameters to'
begin' and 'end' resp. to avoid making people think, that 'max' is
included in the interval. 'end' now isn't, whereas 'begin'
is. That's similar to the use in the STL.
* gslist.c, glist.c: Ok, I'm a moron. When I originally
implemented ENABLE_GC_FRIENDLY, I forgot to include config.h into
the affected files. Now that Alex did that for those two,

View File

@ -1,5 +1,21 @@
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
accurate. Redid g_rand_double() such that it returns 52 bits after
the point instead of 32 as before. That OTOH requires calling
g_rand_int() twice. Overhauled g_rand_int_range(), which is easier
now thanks to the new precision of g_rand_double(). Thanks to
Sverre Johansen <sj@ifi.uio.no> for the hint.
* grand.h: Added g_rand_boolean() and g_random_boolean()
macros. While they could be omitted due to extreme simplicity,
they make intention clearer in code and are therefore good to have.
* grand.c, grand.h: Renamed all 'min' and 'max' parameters to'
begin' and 'end' resp. to avoid making people think, that 'max' is
included in the interval. 'end' now isn't, whereas 'begin'
is. That's similar to the use in the STL.
* gslist.c, glist.c: Ok, I'm a moron. When I originally
implemented ENABLE_GC_FRIENDLY, I forgot to include config.h into
the affected files. Now that Alex did that for those two,

View File

@ -1,5 +1,21 @@
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
accurate. Redid g_rand_double() such that it returns 52 bits after
the point instead of 32 as before. That OTOH requires calling
g_rand_int() twice. Overhauled g_rand_int_range(), which is easier
now thanks to the new precision of g_rand_double(). Thanks to
Sverre Johansen <sj@ifi.uio.no> for the hint.
* grand.h: Added g_rand_boolean() and g_random_boolean()
macros. While they could be omitted due to extreme simplicity,
they make intention clearer in code and are therefore good to have.
* grand.c, grand.h: Renamed all 'min' and 'max' parameters to'
begin' and 'end' resp. to avoid making people think, that 'max' is
included in the interval. 'end' now isn't, whereas 'begin'
is. That's similar to the use in the STL.
* gslist.c, glist.c: Ok, I'm a moron. When I originally
implemented ENABLE_GC_FRIENDLY, I forgot to include config.h into
the affected files. Now that Alex did that for those two,

View File

@ -1,3 +1,10 @@
2000-12-19 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* glib/glib-sections.txt: Added g_rand_boolean and
g_random_boolean macros.
* glib/tmpl/random_numbers.sgml: Updated.
Tue Dec 5 15:41:23 2000 Owen Taylor <otaylor@redhat.com>
* glib/Makefile.am glib/mainloop-states*: add images

View File

@ -1626,11 +1626,13 @@ g_rand_new_with_seed
g_rand_new
g_rand_free
g_rand_set_seed
g_rand_boolean
g_rand_int
g_rand_int_range
g_rand_double
g_rand_double_range
g_random_set_seed
g_random_boolean
g_random_int
g_random_int_range
g_random_double

View File

@ -32,14 +32,6 @@ distributed random numbers, whereas for example the
yield equally distributed numbers.
</para>
<para>
A random binary decision is best implemented by using
<literal>if(g_random_int()&amp;(1<<@a))</literal>, where @a can be every
integer constant from 0 to 31. The Mersenne Twister PRNG is said to
produce highly random lower bits too, but it is common not to rely on
that, so choosing @a to be from 4 to 31 might be wise.
</para>
<!-- ##### SECTION See_Also ##### -->
<para>
@ -78,6 +70,16 @@ accessed through the g_rand_* functions.
@seed:
<!-- ##### MACRO g_rand_boolean ##### -->
<para>
Return a random #gboolean from @rand. This corresponds to a unbiased
coin toss.
</para>
@rand: a #GRand.
@Returns: a random #gboolean.
<!-- ##### FUNCTION g_rand_int ##### -->
@ -89,8 +91,8 @@ accessed through the g_rand_* functions.
@rand:
@min:
@max:
@begin:
@end:
@Returns:
@ -105,8 +107,8 @@ accessed through the g_rand_* functions.
@rand:
@min:
@max:
@begin:
@end:
@Returns:
@ -116,6 +118,14 @@ accessed through the g_rand_* functions.
@seed:
<!-- ##### MACRO g_random_boolean ##### -->
<para>
Return a random #gboolean. This corresponds to a unbiased coin toss.
</para>
@Returns: a random #gboolean.
<!-- ##### FUNCTION g_random_int ##### -->
@ -125,8 +135,8 @@ accessed through the g_rand_* functions.
<!-- ##### FUNCTION g_random_int_range ##### -->
@min:
@max:
@begin:
@end:
@Returns:
@ -139,8 +149,8 @@ accessed through the g_rand_* functions.
<!-- ##### FUNCTION g_random_double_range ##### -->
@min:
@max:
@begin:
@end:
@Returns:

View File

@ -200,71 +200,61 @@ g_rand_int (GRand* rand)
return y;
}
/* transform [0..2^32] -> [0..1] */
#define G_RAND_DOUBLE_TRANSFORM 2.3283064365386962890625e-10
/**
* g_rand_int_range:
* @rand: a #GRand.
* @min: lower closed bound of the interval.
* @max: upper open bound of the interval.
* @begin: lower closed bound of the interval.
* @end: upper open bound of the interval.
*
* Return the next random #gint32 from @rand equaly distributed over
* the range [@min..@max-1].
* the range [@begin..@end-1].
*
* Return value: A random number.
**/
gint32
g_rand_int_range (GRand* rand, gint32 min, gint32 max)
g_rand_int_range (GRand* rand, gint32 begin, gint32 end)
{
guint32 dist = max - min;
guint32 dist = end - begin;
guint32 random;
g_return_val_if_fail (rand != NULL, min);
g_return_val_if_fail (max > min, min);
g_return_val_if_fail (rand != NULL, begin);
g_return_val_if_fail (end > begin, begin);
/* All tricks doing modulo calculations do not have a perfect
* distribution -> We must use the slower way through gdouble for
* maximal quality. */
if (dist <= 0x10000L) /* 2^16 */
{
/* All tricks doing modulo calculations do not have a good
distribution -> We must use this slower method for maximal
quality, but this method is only good for (max - min) <= 2^16 */
/* This method, which only calls g_rand_int once is only good
* for (end - begin) <= 2^16, because we only have 32 bits set
* from the one call to g_rand_int (). */
/* we are using (trans + trans * trans), because g_rand_int only
* covers [0..2^32-1] and thus g_rand_int * trans only covers
* [0..1-2^-32], but the biggest double < 1 is 1-2^-52.
*/
gdouble double_rand = g_rand_int (rand) *
(G_RAND_DOUBLE_TRANSFORM +
G_RAND_DOUBLE_TRANSFORM * G_RAND_DOUBLE_TRANSFORM);
random = (gint32) g_rand_double_range (rand, 0, dist);
/* we'd rather use the following, if -lm is allowed later on:
random = (gint32) floor (g_rand_double_range (rand, 0, dist)); */
random = (gint32) (double_rand * dist);
}
else
{
/* Now it's harder to make it right. We calculate the smallest m,
such that dist < 2 ^ m, then we calculate a random number in
[1..2^32-1] and rightshift it by 32 - m. Then we test, if it
is smaller than dist and if not, get a new number and so
forth until we get a number smaller than dist. We just return
this. */
guint32 border = 0x20000L; /* 2^17 */
guint right_shift = 15; /* 32 - 17 */
if (dist >= 0x80000000) /* in the case of dist > 2^31 our loop
below will be infinite */
{
right_shift = 0;
}
else
{
while (dist >= border)
{
border <<= 1;
right_shift--;
}
}
do
{
random = g_rand_int (rand) >> right_shift;
} while (random >= dist);
/* Now we use g_rand_double_range (), which will set 52 bits for
us, so that it is safe to round and still get a decent
distribution */
random = (gint32) g_rand_double_range (rand, 0, dist);
}
return min + random;
return begin + random;
}
/* transform [0..2^32-1] -> [0..1) */
#define G_RAND_DOUBLE_TRANSFORM 2.3283064365386963e-10
/**
* g_rand_double:
* @rand: a #GRand.
@ -276,25 +266,35 @@ g_rand_int_range (GRand* rand, gint32 min, gint32 max)
**/
gdouble
g_rand_double (GRand* rand)
{
return g_rand_int (rand) * G_RAND_DOUBLE_TRANSFORM;
{
/* We set all 52 bits after the point for this, not only the first
32. Thats why we need two calls to g_rand_int */
gdouble retval = g_rand_int (rand) * G_RAND_DOUBLE_TRANSFORM;
retval = (retval + g_rand_int (rand)) * G_RAND_DOUBLE_TRANSFORM;
/* The following might happen due to very bad rounding luck, but
* actually this should be more than rare, we just try again then */
if (retval >= 1.0)
return g_rand_double (rand);
return retval;
}
/**
* g_rand_double_range:
* @rand: a #GRand.
* @min: lower closed bound of the interval.
* @max: upper open bound of the interval.
* @begin: lower closed bound of the interval.
* @end: upper open bound of the interval.
*
* Return the next random #gdouble from @rand equaly distributed over
* the range [@min..@max).
* the range [@begin..@end).
*
* Return value: A random number.
**/
gdouble
g_rand_double_range (GRand* rand, gdouble min, gdouble max)
g_rand_double_range (GRand* rand, gdouble begin, gdouble end)
{
return g_rand_int (rand) * ((max - min) * G_RAND_DOUBLE_TRANSFORM) + min;
return g_rand_double (rand) * (end - begin) + begin;
}
/**
@ -320,23 +320,23 @@ g_random_int (void)
/**
* g_random_int_range:
* @min: lower closed bound of the interval.
* @max: upper open bound of the interval.
* @begin: lower closed bound of the interval.
* @end: upper open bound of the interval.
*
* Return a random #gint32 equaly distributed over the range
* [@min..@max-1].
* [@begin..@end-1].
*
* Return value: A random number.
**/
gint32
g_random_int_range (gint32 min, gint32 max)
g_random_int_range (gint32 begin, gint32 end)
{
gint32 result;
G_LOCK (global_random);
if (!global_random)
global_random = g_rand_new ();
result = g_rand_int_range (global_random, min, max);
result = g_rand_int_range (global_random, begin, end);
G_UNLOCK (global_random);
return result;
}
@ -363,22 +363,22 @@ g_random_double (void)
/**
* g_random_double_range:
* @min: lower closed bound of the interval.
* @max: upper open bound of the interval.
* @begin: lower closed bound of the interval.
* @end: upper open bound of the interval.
*
* Return a random #gdouble equaly distributed over the range [@min..@max).
* Return a random #gdouble equaly distributed over the range [@begin..@end).
*
* Return value: A random number.
**/
gdouble
g_random_double_range (gdouble min, gdouble max)
g_random_double_range (gdouble begin, gdouble end)
{
double result;
G_LOCK (global_random);
if (!global_random)
global_random = g_rand_new ();
result = g_rand_double_range (global_random, min, max);
result = g_rand_double_range (global_random, begin, end);
G_UNLOCK (global_random);
return result;
}

View File

@ -35,11 +35,11 @@ typedef struct _GRand GRand;
/* GRand - a good and fast random number generator: Mersenne Twister
* see http://www.math.keio.ac.jp/~matumoto/emt.html for more info.
* The range functions return a value in the intervall [min,max).
* The range functions return a value in the intervall [begin, end).
* int -> [0..2^32-1]
* int_range -> [min..max-1]
* int_range -> [begin..end-1]
* double -> [0..1)
* double_range -> [min..max)
* double_range -> [begin..end)
*/
GRand* g_rand_new_with_seed (guint32 seed);
@ -48,22 +48,28 @@ void g_rand_free (GRand *rand);
void g_rand_set_seed (GRand *rand,
guint32 seed);
#define g_rand_boolean(rand) (g_rand_int ((rand)) & (1<<15))
guint32 g_rand_int (GRand *rand);
gint32 g_rand_int_range (GRand *rand,
gint32 min,
gint32 max);
gint32 begin,
gint32 end);
gdouble g_rand_double (GRand *rand);
gdouble g_rand_double_range (GRand *rand,
gdouble min,
gdouble max);
gdouble begin,
gdouble end);
void g_random_set_seed (guint32 seed);
#define g_random_boolean() (g_rand_boolean ((rand)))
guint32 g_random_int (void);
gint32 g_random_int_range (gint32 min,
gint32 max);
gint32 g_random_int_range (gint32 begin,
gint32 end);
gdouble g_random_double (void);
gdouble g_random_double_range (gdouble min,
gdouble max);
gdouble g_random_double_range (gdouble begin,
gdouble end);
G_END_DECLS

120
grand.c
View File

@ -200,71 +200,61 @@ g_rand_int (GRand* rand)
return y;
}
/* transform [0..2^32] -> [0..1] */
#define G_RAND_DOUBLE_TRANSFORM 2.3283064365386962890625e-10
/**
* g_rand_int_range:
* @rand: a #GRand.
* @min: lower closed bound of the interval.
* @max: upper open bound of the interval.
* @begin: lower closed bound of the interval.
* @end: upper open bound of the interval.
*
* Return the next random #gint32 from @rand equaly distributed over
* the range [@min..@max-1].
* the range [@begin..@end-1].
*
* Return value: A random number.
**/
gint32
g_rand_int_range (GRand* rand, gint32 min, gint32 max)
g_rand_int_range (GRand* rand, gint32 begin, gint32 end)
{
guint32 dist = max - min;
guint32 dist = end - begin;
guint32 random;
g_return_val_if_fail (rand != NULL, min);
g_return_val_if_fail (max > min, min);
g_return_val_if_fail (rand != NULL, begin);
g_return_val_if_fail (end > begin, begin);
/* All tricks doing modulo calculations do not have a perfect
* distribution -> We must use the slower way through gdouble for
* maximal quality. */
if (dist <= 0x10000L) /* 2^16 */
{
/* All tricks doing modulo calculations do not have a good
distribution -> We must use this slower method for maximal
quality, but this method is only good for (max - min) <= 2^16 */
/* This method, which only calls g_rand_int once is only good
* for (end - begin) <= 2^16, because we only have 32 bits set
* from the one call to g_rand_int (). */
/* we are using (trans + trans * trans), because g_rand_int only
* covers [0..2^32-1] and thus g_rand_int * trans only covers
* [0..1-2^-32], but the biggest double < 1 is 1-2^-52.
*/
gdouble double_rand = g_rand_int (rand) *
(G_RAND_DOUBLE_TRANSFORM +
G_RAND_DOUBLE_TRANSFORM * G_RAND_DOUBLE_TRANSFORM);
random = (gint32) g_rand_double_range (rand, 0, dist);
/* we'd rather use the following, if -lm is allowed later on:
random = (gint32) floor (g_rand_double_range (rand, 0, dist)); */
random = (gint32) (double_rand * dist);
}
else
{
/* Now it's harder to make it right. We calculate the smallest m,
such that dist < 2 ^ m, then we calculate a random number in
[1..2^32-1] and rightshift it by 32 - m. Then we test, if it
is smaller than dist and if not, get a new number and so
forth until we get a number smaller than dist. We just return
this. */
guint32 border = 0x20000L; /* 2^17 */
guint right_shift = 15; /* 32 - 17 */
if (dist >= 0x80000000) /* in the case of dist > 2^31 our loop
below will be infinite */
{
right_shift = 0;
}
else
{
while (dist >= border)
{
border <<= 1;
right_shift--;
}
}
do
{
random = g_rand_int (rand) >> right_shift;
} while (random >= dist);
/* Now we use g_rand_double_range (), which will set 52 bits for
us, so that it is safe to round and still get a decent
distribution */
random = (gint32) g_rand_double_range (rand, 0, dist);
}
return min + random;
return begin + random;
}
/* transform [0..2^32-1] -> [0..1) */
#define G_RAND_DOUBLE_TRANSFORM 2.3283064365386963e-10
/**
* g_rand_double:
* @rand: a #GRand.
@ -276,25 +266,35 @@ g_rand_int_range (GRand* rand, gint32 min, gint32 max)
**/
gdouble
g_rand_double (GRand* rand)
{
return g_rand_int (rand) * G_RAND_DOUBLE_TRANSFORM;
{
/* We set all 52 bits after the point for this, not only the first
32. Thats why we need two calls to g_rand_int */
gdouble retval = g_rand_int (rand) * G_RAND_DOUBLE_TRANSFORM;
retval = (retval + g_rand_int (rand)) * G_RAND_DOUBLE_TRANSFORM;
/* The following might happen due to very bad rounding luck, but
* actually this should be more than rare, we just try again then */
if (retval >= 1.0)
return g_rand_double (rand);
return retval;
}
/**
* g_rand_double_range:
* @rand: a #GRand.
* @min: lower closed bound of the interval.
* @max: upper open bound of the interval.
* @begin: lower closed bound of the interval.
* @end: upper open bound of the interval.
*
* Return the next random #gdouble from @rand equaly distributed over
* the range [@min..@max).
* the range [@begin..@end).
*
* Return value: A random number.
**/
gdouble
g_rand_double_range (GRand* rand, gdouble min, gdouble max)
g_rand_double_range (GRand* rand, gdouble begin, gdouble end)
{
return g_rand_int (rand) * ((max - min) * G_RAND_DOUBLE_TRANSFORM) + min;
return g_rand_double (rand) * (end - begin) + begin;
}
/**
@ -320,23 +320,23 @@ g_random_int (void)
/**
* g_random_int_range:
* @min: lower closed bound of the interval.
* @max: upper open bound of the interval.
* @begin: lower closed bound of the interval.
* @end: upper open bound of the interval.
*
* Return a random #gint32 equaly distributed over the range
* [@min..@max-1].
* [@begin..@end-1].
*
* Return value: A random number.
**/
gint32
g_random_int_range (gint32 min, gint32 max)
g_random_int_range (gint32 begin, gint32 end)
{
gint32 result;
G_LOCK (global_random);
if (!global_random)
global_random = g_rand_new ();
result = g_rand_int_range (global_random, min, max);
result = g_rand_int_range (global_random, begin, end);
G_UNLOCK (global_random);
return result;
}
@ -363,22 +363,22 @@ g_random_double (void)
/**
* g_random_double_range:
* @min: lower closed bound of the interval.
* @max: upper open bound of the interval.
* @begin: lower closed bound of the interval.
* @end: upper open bound of the interval.
*
* Return a random #gdouble equaly distributed over the range [@min..@max).
* Return a random #gdouble equaly distributed over the range [@begin..@end).
*
* Return value: A random number.
**/
gdouble
g_random_double_range (gdouble min, gdouble max)
g_random_double_range (gdouble begin, gdouble end)
{
double result;
G_LOCK (global_random);
if (!global_random)
global_random = g_rand_new ();
result = g_rand_double_range (global_random, min, max);
result = g_rand_double_range (global_random, begin, end);
G_UNLOCK (global_random);
return result;
}

28
grand.h
View File

@ -35,11 +35,11 @@ typedef struct _GRand GRand;
/* GRand - a good and fast random number generator: Mersenne Twister
* see http://www.math.keio.ac.jp/~matumoto/emt.html for more info.
* The range functions return a value in the intervall [min,max).
* The range functions return a value in the intervall [begin, end).
* int -> [0..2^32-1]
* int_range -> [min..max-1]
* int_range -> [begin..end-1]
* double -> [0..1)
* double_range -> [min..max)
* double_range -> [begin..end)
*/
GRand* g_rand_new_with_seed (guint32 seed);
@ -48,22 +48,28 @@ void g_rand_free (GRand *rand);
void g_rand_set_seed (GRand *rand,
guint32 seed);
#define g_rand_boolean(rand) (g_rand_int ((rand)) & (1<<15))
guint32 g_rand_int (GRand *rand);
gint32 g_rand_int_range (GRand *rand,
gint32 min,
gint32 max);
gint32 begin,
gint32 end);
gdouble g_rand_double (GRand *rand);
gdouble g_rand_double_range (GRand *rand,
gdouble min,
gdouble max);
gdouble begin,
gdouble end);
void g_random_set_seed (guint32 seed);
#define g_random_boolean() (g_rand_boolean ((rand)))
guint32 g_random_int (void);
gint32 g_random_int_range (gint32 min,
gint32 max);
gint32 g_random_int_range (gint32 begin,
gint32 end);
gdouble g_random_double (void);
gdouble g_random_double_range (gdouble min,
gdouble max);
gdouble g_random_double_range (gdouble begin,
gdouble end);
G_END_DECLS