2009-05-21 22:41:07 +00:00
|
|
|
/*------------------------------------------------------------------
|
|
|
|
* Wrapper for the 'SIMD oriented Fast Mersenne Twister.
|
2009-03-03 03:27:01 +00:00
|
|
|
*
|
2009-05-21 22:41:07 +00:00
|
|
|
* SFMT was developed by Mutsuo Saito and Makoto Matsumoto,
|
|
|
|
* Hiroshima University,
|
|
|
|
* http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html)
|
|
|
|
* SFMT was integrated to LDMud by Zesstra@MorgenGrauen (http://mg.mud.de)
|
|
|
|
*------------------------------------------------------------------
|
2009-03-03 03:27:01 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "driver.h"
|
|
|
|
#include "random.h"
|
2009-05-21 22:41:07 +00:00
|
|
|
#include "backend.h"
|
2009-03-03 03:27:01 +00:00
|
|
|
|
2009-05-21 22:41:07 +00:00
|
|
|
/* This is included on purpose so that the compiler may inline some functions.
|
|
|
|
* They are anyway never used anywhere else, all other parts of the driver use
|
|
|
|
* only the wrapper functions in this file.
|
|
|
|
*/
|
|
|
|
#include "random/SFMT.c"
|
2009-03-03 03:27:01 +00:00
|
|
|
|
2009-05-21 22:41:07 +00:00
|
|
|
const unsigned int INIT_ARRAY_SIZE = 156U; // 4*156 == 624 bytes
|
2009-03-03 03:27:01 +00:00
|
|
|
|
2009-05-21 22:41:07 +00:00
|
|
|
// Name of the device/file to seed the PRNG from
|
|
|
|
char * prng_device_name = NULL;
|
2009-03-03 03:27:01 +00:00
|
|
|
|
|
|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
|
|
|
/* Driver interface functions */
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
2009-05-21 22:41:07 +00:00
|
|
|
/* random_number() is in random.h to be inlined. */
|
2009-03-03 03:27:01 +00:00
|
|
|
/* Return a random number in the range 0..n-1.
|
|
|
|
*
|
|
|
|
* The MT FAQ suggests:
|
|
|
|
* If the application is not sensitive to the rounding off error, then please
|
|
|
|
* multiply N to [0,1)-real uniform random numbers and take the integer part
|
|
|
|
* (this is sufficient for most applications).
|
2009-05-21 22:41:07 +00:00
|
|
|
* I use the appropriate functions from the SFMT to generate random numbers on
|
|
|
|
* the [0,1) interval and multiply with N.
|
2009-03-03 03:27:01 +00:00
|
|
|
*/
|
2009-05-21 22:41:07 +00:00
|
|
|
#if SIZEOF_LONG == SIZEOF_CHAR_P
|
|
|
|
uint64_t random_number(uint64_t n) {
|
|
|
|
return genrand_res53() * n;
|
|
|
|
}
|
|
|
|
#elif SIZEOF_INT == SIZEOF_CHAR_P
|
|
|
|
uint32_t random_number(uint32 n) {
|
|
|
|
return genrand_real2() * n;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#error We currently do not yet support a 128 bit integer type used as \
|
|
|
|
svalue number type.
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void seed_random_from_int (uint32_t seed)
|
|
|
|
/* Initialize the generator */
|
|
|
|
|
|
|
|
{
|
|
|
|
#ifdef USE_LDMUD_COMPATIBILITY
|
|
|
|
# ifdef VERBOSE
|
|
|
|
printf("%s Seeding PRNG with: 0x%lx\n"
|
|
|
|
, time_stamp(), (unsigned long)seed);
|
|
|
|
# endif
|
|
|
|
debug_message("%s Seeding PRNG with: 0x%lx\n"
|
|
|
|
, time_stamp(), (unsigned long)seed);
|
|
|
|
#endif
|
|
|
|
init_gen_rand(seed);
|
|
|
|
} /* seed_random_from_int() */
|
2009-03-03 03:27:01 +00:00
|
|
|
|
2009-05-21 22:41:07 +00:00
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
void
|
|
|
|
seed_random(const char *filename)
|
|
|
|
/* Opens the file given by filename and reads 156 uint32_t (624
|
|
|
|
* bytes) from it (most often the file is probably /dev/urandom or
|
|
|
|
* /dev/random). If successful the random number generator will be seeded
|
|
|
|
* by an array of 624 bytes. Otherwise the driver clock will be used as
|
|
|
|
* fallback.
|
|
|
|
*/
|
2009-03-03 03:27:01 +00:00
|
|
|
{
|
2009-05-21 22:41:07 +00:00
|
|
|
FILE *seedsrc = NULL; // Filepointer
|
|
|
|
|
|
|
|
// If we got a NULL pointer or an empty string, don't try to open some
|
|
|
|
// device/file.
|
|
|
|
if (filename != NULL && strlen(filename))
|
|
|
|
seedsrc = fopen(filename,"rb");
|
|
|
|
|
|
|
|
// if we have a file descriptor try to get a suitable amount of 32-bit
|
|
|
|
// values from a file (right now 156 uint32_t / 624 bytes)
|
|
|
|
if (seedsrc) {
|
|
|
|
uint32_t seeddata[INIT_ARRAY_SIZE];
|
|
|
|
size_t count = fread( seeddata, sizeof(uint32), INIT_ARRAY_SIZE,
|
|
|
|
seedsrc );
|
|
|
|
fclose(seedsrc);
|
|
|
|
if( count == INIT_ARRAY_SIZE ) {
|
|
|
|
init_by_array(seeddata, INIT_ARRAY_SIZE ); // seed PRNG
|
|
|
|
#ifdef USE_LDMUD_COMPATIBILITY
|
|
|
|
# ifdef VERBOSE
|
|
|
|
printf("%s Seeding PRNG from %s.\n", time_stamp(),
|
|
|
|
filename);
|
|
|
|
# endif
|
|
|
|
debug_message("%s Seeding PRNG from %s.\n", time_stamp(),
|
|
|
|
filename);
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
} // if (count == INIT_ARRAY_SIZE)
|
|
|
|
} // if (seedsrc)
|
|
|
|
|
|
|
|
// Fall-back: driver clock
|
|
|
|
#ifdef USE_LDMUD_COMPATIBILITY
|
|
|
|
# ifdef VERBOSE
|
|
|
|
printf("%s Seeding PRNG with current driver time\n"
|
|
|
|
, time_stamp());
|
|
|
|
# endif
|
|
|
|
debug_message("%s Seeding PRNG with current driver time\n"
|
|
|
|
, time_stamp());
|
|
|
|
#endif
|
|
|
|
seed_random_from_int((uint32_t)current_time);
|
|
|
|
|
|
|
|
} /* seed_random() */
|
2009-03-03 03:27:01 +00:00
|
|
|
|
|
|
|
/***************************************************************************/
|