#include <unistd.h>
#include <time.h>
+#include "main_bd.h"
+
#if defined(PLATFORM_WINDOWS)
-#include <process.h> /* for getpid() */
+#include <process.h> // for getpid()
+#if (defined(_MSC_VER) && _MSC_VER >= 1400) || defined(__MINGW64_VERSION_MAJOR)
+extern errno_t rand_s (unsigned int *randomValue);
+#endif
#endif
-
-#include "main_bd.h"
/**
* 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)
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;
};
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
*/
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++)
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++;
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)
}
}
- rand->mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
+ rand->mt[0] = 0x80000000UL; // MSB is 1; assuring non-zero initial array
}
/**
{
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++)
return y;
}
+// transform [0..2^32] -> [0..1]
+#define GD_RAND_DOUBLE_TRANSFORM 2.3283064365386962890625e-10
+
/**
* gd_rand_int_range:
* @rand_: a #GdRand
* 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;
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
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;
+}