X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame_bd%2Fbd_random.c;h=fc7998cbdb936718bac7321286d647c7e1722bfa;hb=ba8b3a4699a29152912c319d6f51a09213a73d9e;hp=085308632dca06997cfe8246326934057dd4ac68;hpb=b377a0cc25c12922edb0e92050a552b86e5f7f3a;p=rocksndiamonds.git diff --git a/src/game_bd/bd_random.c b/src/game_bd/bd_random.c index 08530863..fc7998cb 100644 --- a/src/game_bd/bd_random.c +++ b/src/game_bd/bd_random.c @@ -38,9 +38,10 @@ #include #include #include +#include #if defined(PLATFORM_WINDOWS) -#include /* for getpid() */ +#include // for getpid() #endif #include "main_bd.h" @@ -53,14 +54,14 @@ * accessed through the gd_rand_* functions. **/ -/* Period parameters */ +// Period parameters #define N 624 #define M 397 -#define MATRIX_A 0x9908b0df /* constant vector a */ -#define UPPER_MASK 0x80000000 /* most significant w-r bits */ -#define LOWER_MASK 0x7fffffff /* least significant r bits */ +#define MATRIX_A 0x9908b0df // constant vector a +#define UPPER_MASK 0x80000000 // most significant w-r bits +#define LOWER_MASK 0x7fffffff // least significant r bits -/* Tempering parameters */ +// Tempering parameters #define TEMPERING_MASK_B 0x9d2c5680 #define TEMPERING_MASK_C 0xefc60000 #define TEMPERING_SHIFT_U(y) (y >> 11) @@ -70,7 +71,7 @@ struct _GdRand { - unsigned int mt[N]; /* the array for the state vector */ + unsigned int mt[N]; // the array for the state vector unsigned int mti; }; @@ -175,7 +176,7 @@ gd_rand_new (void) seed[2] = getpid (); seed[3] = getppid (); } -#else /* PLATFORM_WINDOWS */ +#else // PLATFORM_WINDOWS /* rand_s() is only available since Visual Studio 2005 and * MinGW-w64 has a wrapper that will emulate rand_s() if it's not in msvcrt */ @@ -253,9 +254,9 @@ gd_rand_set_seed (GdRand *rand, unsigned int seed) if (rand == NULL) return; - /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ - /* In the previous version (see above), MSBs of the */ - /* seed affect only MSBs of the array mt[]. */ + // See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. + // In the previous version (see above), MSBs of the + // seed affect only MSBs of the array mt[]. rand->mt[0] = seed; for (rand->mti = 1; rand->mti < N; rand->mti++) @@ -294,8 +295,8 @@ gd_rand_set_seed_array (GdRand *rand, const unsigned int *seed, unsigned int see for (; k; k--) { rand->mt[i] = ((rand->mt[i] ^ ((rand->mt[i - 1] ^ (rand->mt[i - 1] >> 30)) * 1664525UL)) - + seed[j] + j); /* non linear */ - rand->mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ + + seed[j] + j); // non linear + rand->mt[i] &= 0xffffffffUL; // for WORDSIZE > 32 machines i++; j++; @@ -312,8 +313,8 @@ gd_rand_set_seed_array (GdRand *rand, const unsigned int *seed, unsigned int see for (k = N - 1; k; k--) { rand->mt[i] = ((rand->mt[i] ^ ((rand->mt[i - 1] ^ (rand->mt[i - 1] >> 30)) * 1566083941UL)) - - i); /* non linear */ - rand->mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */ + - i); // non linear + rand->mt[i] &= 0xffffffffUL; // for WORDSIZE > 32 machines i++; if (i >= N) @@ -323,7 +324,7 @@ gd_rand_set_seed_array (GdRand *rand, const unsigned int *seed, unsigned int see } } - rand->mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */ + rand->mt[0] = 0x80000000UL; // MSB is 1; assuring non-zero initial array } /** @@ -349,14 +350,14 @@ gd_rand_int (GdRand *rand) { unsigned int y; static const unsigned int mag01[2] = { 0x0, MATRIX_A }; - /* mag01[x] = x * MATRIX_A for x=0,1 */ + // mag01[x] = x * MATRIX_A for x=0,1 if (rand == NULL) return 0; if (rand->mti >= N) { - /* generate N words at one time */ + // generate N words at one time int kk; for (kk = 0; kk < N - M; kk++) @@ -386,6 +387,9 @@ gd_rand_int (GdRand *rand) return y; } +// transform [0..2^32] -> [0..1] +#define GD_RAND_DOUBLE_TRANSFORM 2.3283064365386962890625e-10 + /** * gd_rand_int_range: * @rand_: a #GdRand @@ -413,9 +417,9 @@ gd_rand_int_range (GdRand *rand, int begin, int end) * multiple of dist less or equal 2^32. */ unsigned int maxvalue; - if (dist <= 0x80000000u) /* 2^31 */ + if (dist <= 0x80000000u) // 2^31 { - /* maxvalue = 2^32 - 1 - (2^32 % dist) */ + // maxvalue = 2^32 - 1 - (2^32 % dist) unsigned int leftover = (0x80000000u % dist) * 2; if (leftover >= dist) leftover -= dist; maxvalue = 0xffffffffu - leftover; @@ -434,18 +438,90 @@ gd_rand_int_range (GdRand *rand, int begin, int end) return begin + random; } +/** + * gd_rand_double: + * @rand_: a #GRand + * + * Returns the next random #double from @rand_ equally distributed over + * the range [0..1). + * + * Returns: a random number + */ +double +gd_rand_double (GdRand *rand) +{ + /* We set all 52 bits after the point for this, not only the first + 32. That's why we need two calls to gd_rand_int */ + double retval = gd_rand_int(rand) * GD_RAND_DOUBLE_TRANSFORM; + retval = (retval + gd_rand_int(rand)) * GD_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 gd_rand_double (rand); + + return retval; +} + +/** + * gd_rand_double_range: + * @rand_: a #GRand + * @begin: lower closed bound of the interval + * @end: upper open bound of the interval + * + * Returns the next random #double from @rand_ equally distributed over + * the range [@begin..@end). + * + * Returns: a random number + */ +double +gd_rand_double_range (GdRand *rand, double begin, double end) +{ + double r; + + r = gd_rand_double(rand); + + return r * end - (r - 1) * begin; +} + static GdRand * get_global_random (void) { static GdRand *global_random; - /* called while locked */ + // called while locked if (!global_random) global_random = gd_rand_new(); return global_random; } +/** + * gd_random_boolean: + * + * Returns a random #gboolean. + * This corresponds to an unbiased coin toss. + * + * Returns: a random #gboolean + */ +/** + * gd_random_int: + * + * Return a random #guint32 equally distributed over the range + * [0..2^32-1]. + * + * Returns: a random number + */ +unsigned int +gd_random_int (void) +{ + unsigned int result; + + result = gd_rand_int(get_global_random()); + + return result; +} + /** * gd_random_int_range: * @begin: lower closed bound of the interval @@ -465,3 +541,40 @@ gd_random_int_range (int begin, int end) return result; } + +/** + * gd_random_double: + * + * Returns a random #double equally distributed over the range [0..1). + * + * Returns: a random number + */ +double +gd_random_double (void) +{ + double result; + + result = gd_rand_double(get_global_random()); + + return result; +} + +/** + * gd_random_double_range: + * @begin: lower closed bound of the interval + * @end: upper open bound of the interval + * + * Returns a random #double equally distributed over the range + * [@begin..@end). + * + * Returns: a random number + */ +double +gd_random_double_range (double begin, double end) +{ + double result; + + result = gd_rand_double_range(get_global_random(), begin, end); + + return result; +}