FlashGraph-ng
A new frontier in large-scale graph analysis and data mining
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Pages
rand_gen.h
1 #ifndef __RAND_GEN_H__
2 #define __RAND_GEN_H__
3 
4 /*
5  * Copyright 2014 Open Connectome Project (http://openconnecto.me)
6  * Written by Da Zheng (zhengda1936@gmail.com)
7  *
8  * This file is part of FlashMatrix.
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  */
22 
23 #include <memory>
24 #include <random>
25 
26 #include "generic_type.h"
27 
28 namespace fm
29 {
30 
31 class rand_gen
32 {
33 protected:
34  static unsigned int gen_rand_seed();
35 public:
36  typedef std::shared_ptr<rand_gen> ptr;
37  template<class T>
38  static ptr create_randu(T min, T max);
39  template<class T>
40  static ptr create_randu(T min, T max, T seed);
41 
42  template<class T>
43  static ptr create_randn(T mean, T stddev);
44  template<class T>
45  static ptr create_randn(T mean, T stddev, T seed);
46 
47  virtual void gen(void *buf, size_t len) = 0;
48  virtual const scalar_type &get_type() const = 0;
49 };
50 
51 template<class T>
52 class urand_gen_impl: public rand_gen
53 {
54  // By default, it generates 32-bit integers.
55  typedef std::mt19937 base_generator_type;
56  // By default, I assume it generates integers.
57  typedef std::uniform_int_distribution<T> distribution_type;
58 
59  base_generator_type generator;
60  distribution_type dist;
61 public:
62  urand_gen_impl(T min, T max, T seed): generator(seed), dist(min, max) {
63  }
64 
65  void gen(void *buf, size_t len) {
66  T *t_buf = (T *) buf;
67  for (size_t i = 0; i < len; i++)
68  t_buf[i] = dist(generator);
69  }
70 
71  virtual const scalar_type &get_type() const {
72  return get_scalar_type<T>();
73  }
74 };
75 
76 template<>
77 class urand_gen_impl<int64_t>: public rand_gen
78 {
79  typedef std::mt19937_64 base_generator_type;
80  typedef std::uniform_int_distribution<int64_t> distribution_type;
81 
82  base_generator_type generator;
83  distribution_type dist;
84 public:
85  urand_gen_impl(int64_t min, int64_t max,
86  int64_t seed): generator(seed), dist(min, max) {
87  }
88 
89  void gen(void *buf, size_t len);
90 
91  virtual const scalar_type &get_type() const {
92  return get_scalar_type<int64_t>();
93  }
94 };
95 
96 template<>
97 class urand_gen_impl<float>: public rand_gen
98 {
99  typedef std::mt19937 base_generator_type;
100  typedef std::uniform_real_distribution<float> distribution_type;
101 
102  base_generator_type generator;
103  distribution_type dist;
104 public:
105  urand_gen_impl(float min, float max,
106  float seed): generator((int32_t) seed), dist(min, max) {
107  }
108 
109  void gen(void *buf, size_t len);
110 
111  virtual const scalar_type &get_type() const {
112  return get_scalar_type<float>();
113  }
114 };
115 
116 template<>
117 class urand_gen_impl<double>: public rand_gen
118 {
119  typedef std::mt19937_64 base_generator_type;
120  typedef std::uniform_real_distribution<double> distribution_type;
121 
122  base_generator_type generator;
123  distribution_type dist;
124 public:
125  urand_gen_impl(double min, double max,
126  double seed): generator((int64_t) seed), dist(min, max) {
127  }
128 
129  void gen(void *buf, size_t len);
130 
131  virtual const scalar_type &get_type() const {
132  return get_scalar_type<double>();
133  }
134 };
135 
136 template<>
137 class urand_gen_impl<long double>: public rand_gen
138 {
139  typedef std::mt19937_64 base_generator_type;
140  typedef std::uniform_real_distribution<double> distribution_type;
141 
142  base_generator_type generator;
143  distribution_type dist;
144 public:
145  urand_gen_impl(long double min, long double max,
146  long double seed): generator((int64_t) seed), dist(min, max) {
147  }
148 
149  void gen(void *buf, size_t len);
150 
151  virtual const scalar_type &get_type() const {
152  return get_scalar_type<long double>();
153  }
154 };
155 
156 template<>
157 class urand_gen_impl<bool>: public rand_gen
158 {
159  typedef std::mt19937 base_generator_type;
160  typedef std::uniform_int_distribution<int> distribution_type;
161 
162  base_generator_type generator;
163  distribution_type dist;
164 public:
165  urand_gen_impl(bool min, bool max,
166  // Use a better seed for the generator.
167  bool seed): generator(gen_rand_seed()), dist(0, 1) {
168  }
169 
170  void gen(void *buf, size_t len);
171 
172  virtual const scalar_type &get_type() const {
173  return get_scalar_type<bool>();
174  }
175 };
176 
177 template<class T>
178 rand_gen::ptr rand_gen::create_randu(T min, T max)
179 {
180  return rand_gen::ptr(new urand_gen_impl<T>(min, max, gen_rand_seed()));
181 }
182 
183 template<class T>
184 rand_gen::ptr rand_gen::create_randu(T min, T max, T seed)
185 {
186  return rand_gen::ptr(new urand_gen_impl<T>(min, max, seed));
187 }
188 
189 template<class T>
190 class nrand_gen_impl: public rand_gen
191 {
192  // By default, it generates 32-bit integers.
193  typedef std::mt19937 base_generator_type;
194  // By default, I assume it generates integers.
195  typedef std::normal_distribution<T> distribution_type;
196 
197  base_generator_type generator;
198  distribution_type dist;
199 public:
200  nrand_gen_impl(T mean, T stddev, T seed): generator(seed), dist(mean, stddev) {
201  }
202 
203  void gen(void *buf, size_t len) {
204  T *t_buf = (T *) buf;
205  for (size_t i = 0; i < len; i++)
206  t_buf[i] = dist(generator);
207  }
208 
209  virtual const scalar_type &get_type() const {
210  return get_scalar_type<T>();
211  }
212 };
213 
214 template<class T>
215 rand_gen::ptr rand_gen::create_randn(T mean, T stddev)
216 {
217  return rand_gen::ptr(new nrand_gen_impl<T>(mean, stddev, gen_rand_seed()));
218 }
219 
220 template<class T>
221 rand_gen::ptr rand_gen::create_randn(T mean, T stddev, T seed)
222 {
223  return rand_gen::ptr(new nrand_gen_impl<T>(mean, stddev, seed));
224 }
225 
226 }
227 
228 #endif