55#include < memory>
66#include < random>
77#include < iostream>
8+ #include < type_traits>
89
10+ template <typename T>
911struct float_number_generator {
10- virtual double new_float () = 0;
12+ virtual T new_float () = 0;
1113 virtual std::string describe () = 0;
1214 virtual ~float_number_generator () = default ;
1315};
1416
15- struct uniform_generator : float_number_generator {
17+ template <typename T>
18+ struct uniform_generator : float_number_generator<T> {
1619 std::random_device rd;
17- std::mt19937 gen;
18- std::uniform_real_distribution<double > dis;
19- explicit uniform_generator (double a = 0 , double b = 1 )
20+ std::mt19937_64 gen;
21+ std::uniform_real_distribution<T > dis;
22+ explicit uniform_generator (T a = 0.0 , T b = 1.0 )
2023 : rd(), gen(rd()), dis(a, b) {}
2124 std::string describe () override {
2225 return std::string (" generate random numbers uniformly in the interval [" ) +
2326 std::to_string ((dis.min )()) + std::string (" ," ) +
2427 std::to_string ((dis.max )()) + std::string (" ]" );
2528 }
26- double new_float () override { return dis (gen); }
29+ T new_float () override { return dis (gen); }
2730};
2831
29- struct integer_uniform_generator : float_number_generator {
32+ template <typename T>
33+ struct integer_uniform_generator : float_number_generator<T> {
3034 std::random_device rd;
31- std::mt19937 gen;
35+ std::mt19937_64 gen;
3236 std::uniform_int_distribution<uint64_t > dis;
3337 explicit integer_uniform_generator (uint64_t a = 0 , uint64_t b = 1 )
3438 : rd(), gen(rd()), dis(a, b) {}
3539 std::string describe () override {
3640 return std::string (
37- " generate random untegers numbers uniformly in the interval [" ) +
41+ " generate random integers numbers uniformly in the interval [" ) +
3842 std::to_string ((dis.min )()) + std::string (" ," ) +
3943 std::to_string ((dis.max )()) + std::string (" ]" );
4044 }
41- double new_float () override { return dis (gen); }
45+ T new_float () override { return dis (gen); }
4246};
4347
44- struct one_over_rand32 : float_number_generator {
48+ template <typename T>
49+ struct simple_uniform : float_number_generator<T> {
50+ using gen_type = std::conditional_t <sizeof (T) == 4 , std::mt19937, std::mt19937_64>;
4551 std::random_device rd;
46- std::mt19937 gen;
47- explicit one_over_rand32 () : rd(), gen(rd()) {}
48- std::string describe () override { return " 1 / rand()" ; }
49- double new_float () override {
50- auto g = gen ();
51- while (g == 0 ) {
52- g = gen ();
53- }
54- double x = 1.0 / double (g);
55- return x;
56- }
57- };
58-
59- struct simple_uniform32 : float_number_generator {
60- std::random_device rd;
61- std::mt19937 gen;
62- explicit simple_uniform32 () : rd(), gen(rd()) {}
52+ gen_type gen;
53+ explicit simple_uniform () : rd(), gen(rd()) {}
6354 std::string describe () override { return " rand() / 0xFFFFFFFF " ; }
64- double new_float () override {
65- double x = double (gen ()) / double ((std::mt19937:: max)() );
55+ T new_float () override {
56+ const T x = T (gen ()) / gen. max ( );
6657 return x;
6758 }
6859};
6960
70- struct simple_int32 : float_number_generator {
61+ template <typename T>
62+ struct simple_int : float_number_generator<T> {
63+ using gen_type = std::conditional_t <sizeof (T) == 4 , std::mt19937, std::mt19937_64>;
7164 std::random_device rd;
72- std::mt19937 gen;
73- explicit simple_int32 () : rd(), gen(rd()) {}
65+ std::mt19937_64 gen;
7466 std::string describe () override { return " rand()" ; }
75- double new_float () override { return gen (); }
67+ explicit simple_int () : rd(), gen(rd()) {}
68+ T new_float () override { return gen (); }
7669};
7770
78- struct simple_int64 : float_number_generator {
71+ template <typename T>
72+ struct one_over_rand : float_number_generator<T> {
73+ using gen_type = std::conditional_t <sizeof (T) == 4 , std::mt19937, std::mt19937_64>;
7974 std::random_device rd;
80- std::mt19937_64 gen;
81- std::string describe () override { return " rand64()" ; }
82- explicit simple_int64 () : rd(), gen(rd()) {}
83- double new_float () override { return gen (); }
75+ gen_type gen;
76+ explicit one_over_rand () : rd(), gen(rd()) {}
77+ std::string describe () override { return " 1 / rand()" ; }
78+ T new_float () override {
79+ auto g = gen ();
80+ while (g == 0 ) {
81+ g = gen ();
82+ }
83+ const T x = T (1.0 ) / T (g);
84+ return x;
85+ }
8486};
8587
86- constexpr std::array<const char *, 6 > model_names = {
87- " uniform" , " one_over_rand32 " ,
88- " simple_uniform32 " , " simple_int32 " ,
89- " int_e_int " , " simple_int64 "
88+ constexpr std::array<const char *, 5 > model_names = {
89+ " uniform" , " integer_uniform " ,
90+ " simple_uniform " , " simple_int " ,
91+ " one_over_rand "
9092};
9193
92- inline std::unique_ptr<float_number_generator>
94+ template <typename T>
95+ inline std::unique_ptr<float_number_generator<T>>
9396get_generator_by_name (std::string name) {
9497 std::cout << " available models (-m): " ;
9598 for (std::string name : model_names) {
@@ -99,23 +102,23 @@ get_generator_by_name(std::string name) {
99102
100103 // This is naive, but also not very important.
101104 if (name == " uniform" ) {
102- return std::unique_ptr<float_number_generator> (new uniform_generator ());
105+ return std::unique_ptr<float_number_generator<T>> (new uniform_generator<T> ());
103106 }
104- if (name == " one_over_rand32 " ) {
105- return std::unique_ptr<float_number_generator> (new one_over_rand32 ());
107+ if (name == " integer_uniform " ) {
108+ return std::unique_ptr<float_number_generator<T>> (new integer_uniform_generator<T> ());
106109 }
107- if (name == " simple_uniform32 " ) {
108- return std::unique_ptr<float_number_generator> (new simple_uniform32 ());
110+ if (name == " simple_uniform " ) {
111+ return std::unique_ptr<float_number_generator<T>> (new simple_uniform<T> ());
109112 }
110- if (name == " simple_int32 " ) {
111- return std::unique_ptr<float_number_generator> (new simple_int32 ());
113+ if (name == " simple_int " ) {
114+ return std::unique_ptr<float_number_generator<T>> (new simple_int<T> ());
112115 }
113- if (name == " simple_int64 " ) {
114- return std::unique_ptr<float_number_generator> (new simple_int64 ());
116+ if (name == " one_over_rand " ) {
117+ return std::unique_ptr<float_number_generator<T>> (new one_over_rand<T> ());
115118 }
116119 std::cerr << " I do not recognize " << name << std::endl;
117120 std::cerr << " Warning: falling back on uniform generator. " << std::endl;
118- return std::unique_ptr<float_number_generator> (new uniform_generator ());
121+ return std::unique_ptr<float_number_generator<T>> (new uniform_generator<T> ());
119122}
120123
121124#endif
0 commit comments