diff options
| -rw-r--r-- | src/func.cc | 47 | 
1 files changed, 34 insertions, 13 deletions
| diff --git a/src/func.cc b/src/func.cc index e427bf2..5dcb3e9 100644 --- a/src/func.cc +++ b/src/func.cc @@ -35,6 +35,28 @@  #include "stl-utils.h"  #include "printutils.h" +/* + Random numbers + + Newer versions of boost/C++ include a non-deterministic random_device and + auto/bind()s for random function objects, but we are supporting older systems. +*/ + +#include <boost/random/mersenne_twister.hpp> +#include <boost/random/uniform_real_distribution.hpp> + +#ifdef __WIN32__ +#include <process.h> +int process_id = _getpid(); +#else +#include <sys/types.h> +#include <unistd.h> +int process_id = getpid(); +#endif + +boost::random::mt19937 deterministic_rng; +boost::random::mt19937 lessdeterministic_rng( std::time(0) + process_id ); +  AbstractFunction::~AbstractFunction()  {  } @@ -119,24 +141,15 @@ Value builtin_sign(const Context *, const std::vector<std::string>&, const std::  	return Value();  } -double frand()  -{  -    return rand()/(double(RAND_MAX)+1);  -}  - -double frand(double min, double max)  -{  -    return (min>max) ? frand()*(min-max)+max : frand()*(max-min)+min;   -}  -  Value builtin_rands(const Context *, const std::vector<std::string>&, const std::vector<Value> &args)  { +	bool deterministic = false;  	if (args.size() == 3 &&  			args[0].type() == Value::NUMBER &&   			args[1].type() == Value::NUMBER &&   			args[2].type() == Value::NUMBER)  	{ -		srand((unsigned int)time(0)); +		deterministic = false;  	}  	else if (args.size() == 4 &&   					 args[0].type() == Value::NUMBER &&  @@ -144,16 +157,24 @@ Value builtin_rands(const Context *, const std::vector<std::string>&, const std:  					 args[2].type() == Value::NUMBER &&   					 args[3].type() == Value::NUMBER)  	{ -		srand((unsigned int)args[3].toDouble()); +		deterministic_rng.seed( (unsigned int) args[3].toDouble() ); +		deterministic = true;  	}  	else  	{  		return Value();  	} +	double min = std::min( args[0].toDouble(), args[1].toDouble() ); +	double max = std::max( args[0].toDouble(), args[1].toDouble() ); +	boost::random::uniform_real_distribution<> distributor( min, max );  	Value::VectorType vec;  	for (int i=0; i<args[2].toDouble(); i++) { -		vec.push_back(Value(frand(args[0].toDouble(), args[1].toDouble()))); +		if ( deterministic ) { +			vec.push_back( Value( distributor( deterministic_rng ) ) ); +		} else { +			vec.push_back( Value( distributor( lessdeterministic_rng ) ) ); +		}  	}  	return Value(vec); | 
