00001
00002
00003 #include "osl/hash/hashRandom.h"
00004 #include "osl/misc/milliSeconds.h"
00005
00006 #include <boost/random/mersenne_twister.hpp>
00007 #include <boost/random/uniform_01.hpp>
00008 #include <boost/noncopyable.hpp>
00009 #include <cmath>
00010
00011 int osl::hash::HashRandom::table[osl::hash::HashRandom::Length];
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 namespace osl
00033 {
00034 class normal_distribution : boost::noncopyable
00035 {
00036 public:
00037 explicit normal_distribution(const double& mean_arg = double(0),
00038 const double& sigma_arg = double(1))
00039 : _mean(mean_arg), _sigma(sigma_arg),
00040 _r1(0), _r2(0), _cached_rho(0),
00041 _valid(false)
00042 {
00043 assert(_sigma >= double(0));
00044 }
00045 double mean() const { return _mean; }
00046 double sigma() const { return _sigma; }
00047 void reset() { _valid = false; }
00048 template<class Engine>
00049 double operator()(Engine& eng)
00050 {
00051 if(!_valid) {
00052 _r1 = eng();
00053 _r2 = eng();
00054 _cached_rho = sqrt(-double(2) * log(double(1)-_r2));
00055 _valid = true;
00056 } else {
00057 _valid = false;
00058 }
00059 const double pi = double(3.14159265358979323846);
00060 return _cached_rho * (_valid ?
00061 cos(double(2)*pi*_r1) :
00062 sin(double(2)*pi*_r1))
00063 * _sigma + _mean;
00064 }
00065 private:
00066 double _mean, _sigma;
00067 double _r1, _r2, _cached_rho;
00068 bool _valid;
00069 };
00070 }
00071
00072
00073
00074
00075
00076 void osl::hash::HashRandom::setUp(double sigma)
00077 {
00078 static boost::mt11213b mt_random(MilliSeconds::now().value());
00079 static boost::uniform_01<boost::mt11213b> u0(mt_random);
00080
00081 normal_distribution n(0, sigma);
00082 for (size_t i=0; i<Length; ++i)
00083 table[i] = static_cast<int>(n(u0))/2*2;
00084 }
00085