//  random.hpp
//  Copyright (C) 2008  Chipset
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as       
//  published by the Free Software Foundation, either version 3 of the    
//  License, or (at your option) any later version. 
//    
//  but WITHOUT ANY WARRANTY; without even the implied warranty of 
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with this program. If not, see <http://www.gnu.org/licenses/>.   
//

#ifndef RANDOM_HPP_
#define RANDOM_HPP_
#include 
<ctime>

class random
{
public:
  
explicit random(unsigned long s = 0) : seed(s)
  {
    
if (0 == seed) seed = std::time(0);
    randomize();
  }
  
void reset(unsigned long s = 0)
  {
    seed 
= s;
    
if (0 == seed) seed = std::time(0);
    randomize();
  }
  unsigned 
long rand()
  {
  
//returns a random integer in the range [0, -1UL)
    randomize();
    
return seed;
  }
  
double real()
  {
  
//returns a random real number in the range [0.0, 1.0)
    randomize();
    
return double(seed) / -1UL;
  }
private:
  unsigned 
long seed;
  
void randomize() { seed = 1103515245UL * seed + 12345UL; }
};

class rand_help
{
  
static random r;
public:
  rand_help() {}
 
void operator()(unsigned long s) { r.reset(s); }
  unsigned 
long operator()() const { return r.rand(); }
 
double operator()(double) { return r.real(); }
};
random rand_help:: r;

extern
void srandom(unsigned long ns = 0) { rand_help()(ns); } //reset seed
extern unsigned long irand() { return rand_help()(); }         //negative numbers disallowed
extern double drand() { return rand_help()(1.0); }             //for real numbers

#endif  // RANDOM_HPP_

//以上随机数产生器产生的随机数比rand()产生的随机数更加随机(可以用数学方法检验),
//范围更大(一目了然),速度更快(测试一下便知,稍加修改我还可以让它再快一些,如果有必要)。

/*假设随机数均匀分布为理想分布, 粗略估计随机性*/
#include 
<iostream>
#include 
<vector>
#include 
<iomanip>
#include 
"random.hpp"
int main()
{
  srand(time(
0));
  
//SZ分别取值2^3, 2^4, , 2^15进行测试
  const size_t SZ = 1 << 15;
  std::vector
<unsigned> v1(SZ), v3(SZ);
  std::vector
<unsigned> v2(SZ), v4(SZ);
  
for(size_t i = 0; i < SZ; ++i)
  {
    
++v1[rand() % SZ];//对应元素计数 ,理论上v1[0] ~ v1[SZ - 1]之间每个都应该是1
    ++v2[irand() % SZ];
  }

  
for(size_t i = 0; i < SZ; ++i)
  {
    
++v3[v1[i]]; //统计频度
    ++v4[v2[i]];
  }
  
//假设[0, SSZ)之间不存在间断点, (即使有间断点也无所谓,我们只做粗略模糊统计,因为没有必要那么精确)
  
//最理想的显示结果应该是0:    0,   1:   SZ,    2:    0,   3:    0,   4:    0,   other:    0
  
//0:表示间断,1:表示均匀,2:, 3:, 4:, other: 都表示不同程度的重复
  const size_t SSZ = 5;
  std::cout.fill(
' ');
  
for(size_t i = 0; i < SSZ; ++i)
    std::cout 
<< i << "" << std::setw(SSZ) << v3[i] << ",   ";
  std::cout 
<< "other: " << std::setw(SSZ)
            
<< v3.size() - v3[0- v3[1- v3[2- v3[3- v3[4<< '\n';
  
for(size_t i = 0; i < SSZ; ++i)
    std::cout 
<< i << "" << std::setw(SSZ) << v4[i] << ",   ";
  std::cout 
<< "other: " << std::setw(SSZ)
            
<< v4.size() - v4[0- v4[1- v4[2- v4[3- v4[4<< '\n';
  system(
"pause");
}


//做速度测试
#include <iostream>
#include 
<ctime>
#include 
<cstdlib>
#include 
<windows.h>
#include 
"random.hpp"

int main()
{
  
const size_t SZ = 1 << 27;
  std::cout 
<< "generating random numbers in progress \n";
  std::cout 
<< SZ << " random numbers generated.\n";
  std::cout 
<< "random used: ";
  Sleep(
1000);
  std::clock_t time 
= clock();
  
for(size_t i = 0; i < SZ; ++i)
    irand();
  std::cout 
<< clock() - time << "ms, ";

  std::cout 
<< "rand() used: ";
  Sleep(
1000);
  std::srand(std::time(
0));
  std::clock_t t 
= clock();
  
for(size_t i = 0; i < SZ; ++i)
    std::rand();
  std::cout 
<< clock() - t << "ms\n";

  std::system(
"PAUSE");
  
return 0;
}