Expression Templates Library (ETL)
bernoulli.hpp
1 //=======================================================================
2 // Copyright (c) 2014-2023 Baptiste Wicht
3 // Distributed under the terms of the MIT License.
4 // (See accompanying file LICENSE or copy at
5 // http://opensource.org/licenses/MIT)
6 //=======================================================================
7 
8 #pragma once
9 
11 
12 namespace etl {
13 
18 template <typename T>
20  static constexpr bool linear = true;
21  static constexpr bool thread_safe = false;
22 
28  template <vector_mode_t V>
29  static constexpr bool vectorizable = false;
30 
34  template <typename E>
35  static constexpr bool gpu_computable = (is_single_precision_t<T> && impl::egblas::has_sbernoulli_sample_seed)
36  || (is_double_precision_t<T> && impl::egblas::has_dbernoulli_sample_seed);
37 
42  static constexpr int complexity() {
43  return 1;
44  }
45 
51  static T apply(const T& x) {
52  static random_engine rand_engine(std::time(nullptr));
53  static std::uniform_real_distribution<double> distribution(0.0, 1.0);
54 
55  return x > distribution(rand_engine) ? 1.0 : 0.0;
56  }
57 
65  template <typename X, typename Y>
66  static auto gpu_compute_hint(const X & x, Y& y) noexcept {
67  static random_engine rand_engine(std::time(nullptr));
68 
69  std::uniform_int_distribution<long> seed_dist;
70 
71  decltype(auto) t1 = smart_gpu_compute_hint(x, y);
72 
73  auto t2 = force_temporary_gpu_dim_only(t1);
74 
75  T alpha(1);
76  impl::egblas::bernoulli_sample_seed(etl::size(y), alpha, t1.gpu_memory(), 1, t2.gpu_memory(), 1, seed_dist(rand_engine));
77 
78  return t2;
79  }
80 
87  template <typename X, typename Y>
88  static Y& gpu_compute(const X & x, Y& y) noexcept {
89  static random_engine rand_engine(std::time(nullptr));
90 
91  std::uniform_int_distribution<long> seed_dist;
92 
93  decltype(auto) t1 = select_smart_gpu_compute(x, y);
94 
95  T alpha(1);
96  impl::egblas::bernoulli_sample_seed(etl::size(y), alpha, t1.gpu_memory(), 1, y.gpu_memory(), 1, seed_dist(rand_engine));
97 
98  y.validate_gpu();
99  y.invalidate_cpu();
100 
101  return y;
102  }
103 
108  static std::string desc() noexcept {
109  return "bernoulli";
110  }
111 };
112 
117 template <typename G, typename T>
119  static constexpr bool linear = true;
120  static constexpr bool thread_safe = false;
121 
122 private:
123  G& rand_engine;
124 
125 public:
129  explicit bernoulli_unary_g_op(G& rand_engine) : rand_engine(rand_engine) {
130  //Nothing else to init
131  }
132 
138  template <vector_mode_t V>
139  static constexpr bool vectorizable = false;
140 
144  template <typename E>
145  static constexpr bool gpu_computable = (is_single_precision_t<T> && impl::egblas::has_sbernoulli_sample_seed)
146  || (is_double_precision_t<T> && impl::egblas::has_dbernoulli_sample_seed);
147 
153  T apply(const T& x) const {
154  std::uniform_real_distribution<double> distribution(0.0, 1.0);
155 
156  return x > distribution(rand_engine) ? 1.0 : 0.0;
157  }
158 
166  template <typename X, typename Y>
167  auto gpu_compute_hint(const X & x, Y& y) const noexcept {
168  std::uniform_int_distribution<long> seed_dist;
169 
170  decltype(auto) t1 = smart_gpu_compute_hint(x, y);
171 
172  auto t2 = force_temporary_gpu_dim_only(t1);
173 
174  T alpha(1);
175  impl::egblas::bernoulli_sample_seed(etl::size(y), alpha, t1.gpu_memory(), 1, t2.gpu_memory(), 1, seed_dist(rand_engine));
176 
177  return t2;
178  }
179 
186  template <typename X, typename Y>
187  Y& gpu_compute(const X & x, Y& y) const noexcept {
188  std::uniform_int_distribution<long> seed_dist;
189 
190  decltype(auto) t1 = select_smart_gpu_compute(x, y);
191 
192  T alpha(1);
193  impl::egblas::bernoulli_sample_seed(etl::size(y), alpha, t1.gpu_memory(), 1, y.gpu_memory(), 1, seed_dist(rand_engine));
194 
195  y.validate_gpu();
196  y.invalidate_cpu();
197 
198  return y;
199  }
200 
205  static std::string desc() noexcept {
206  return "bernoulli";
207  }
208 };
209 
214 template <typename T>
216  static constexpr bool linear = true;
217  static constexpr bool thread_safe = false;
218 
224  template <vector_mode_t V>
225  static constexpr bool vectorizable = false;
226 
230  template <typename E>
231  static constexpr bool gpu_computable = (is_single_precision_t<T> && impl::egblas::has_bernoulli_sample_prepare)
232  || (is_double_precision_t<T> && impl::egblas::has_bernoulli_sample_prepare);
233 
234 private:
235  mutable random_engine rand_engine;
236  std::shared_ptr<void*> states;
237 
238 public:
242  state_bernoulli_unary_op() : rand_engine(std::time(nullptr)) {
243  if constexpr (impl::egblas::has_bernoulli_sample_prepare) {
244  states = std::make_shared<void*>();
245  *states = impl::egblas::bernoulli_sample_prepare();
246  }
247  }
248 
252  explicit state_bernoulli_unary_op(const std::shared_ptr<void*> states) : rand_engine(std::time(nullptr)) {
253  if constexpr (impl::egblas::has_bernoulli_sample_prepare) {
254  this->states = states;
255 
256  if (!*this->states) {
257  std::uniform_int_distribution<long> seed_dist;
258  *this->states = impl::egblas::bernoulli_sample_prepare_seed(seed_dist(rand_engine));
259  }
260  }
261  }
262 
268  T apply(const T& x) const {
269  std::uniform_real_distribution<double> distribution(0.0, 1.0);
270 
271  return x > distribution(rand_engine) ? 1.0 : 0.0;
272  }
273 
281  template <typename X, typename Y>
282  auto gpu_compute_hint(const X & x, Y& y) const noexcept {
283  decltype(auto) t1 = smart_gpu_compute_hint(x, y);
284 
285  auto t2 = force_temporary_gpu_dim_only(t1);
286 
287  T alpha(1);
288  impl::egblas::bernoulli_sample_states(etl::size(y), alpha, t1.gpu_memory(), 1, t2.gpu_memory(), 1, *states);
289 
290  return t2;
291  }
298  template <typename X, typename Y>
299  Y& gpu_compute(const X & x, Y& y) const noexcept {
300  decltype(auto) t1 = select_smart_gpu_compute(x, y);
301 
302  T alpha(1);
303  impl::egblas::bernoulli_sample_states(etl::size(y), alpha, t1.gpu_memory(), 1, y.gpu_memory(), 1, *states);
304 
305  y.validate_gpu();
306  y.invalidate_cpu();
307 
308  return y;
309  }
310 
315  static std::string desc() noexcept {
316  return "bernoulli";
317  }
318 };
319 
324 template <typename G, typename T>
326  static constexpr bool linear = true;
327  static constexpr bool thread_safe = false;
328 
334  template <vector_mode_t V>
335  static constexpr bool vectorizable = false;
336 
340  template <typename E>
341  static constexpr bool gpu_computable = (is_single_precision_t<T> && impl::egblas::has_sbernoulli_sample_seed)
342  || (is_double_precision_t<T> && impl::egblas::has_dbernoulli_sample_seed);
343 
344 private:
345  G& rand_engine;
346  std::shared_ptr<void*> states;
347 
348 public:
352  explicit state_bernoulli_unary_g_op(G& rand_engine) : rand_engine(rand_engine) {
353  if constexpr (impl::egblas::has_bernoulli_sample_prepare) {
354  std::uniform_int_distribution<long> seed_dist;
355 
356  states = std::make_shared<void*>();
357  *states = impl::egblas::bernoulli_sample_prepare_seed(seed_dist(rand_engine));
358  }
359  }
360 
364  state_bernoulli_unary_g_op(G& rand_engine, const std::shared_ptr<void*> & states) : rand_engine(rand_engine) {
365  if constexpr (impl::egblas::has_bernoulli_sample_prepare) {
366  this->states = states;
367 
368  if (!*this->states) {
369  std::uniform_int_distribution<long> seed_dist;
370  *this->states = impl::egblas::bernoulli_sample_prepare_seed(seed_dist(rand_engine));
371  }
372  }
373  }
374 
380  T apply(const T& x) const {
381  std::uniform_real_distribution<double> distribution(0.0, 1.0);
382 
383  return x > distribution(rand_engine) ? 1.0 : 0.0;
384  }
385 
393  template <typename X, typename Y>
394  auto gpu_compute_hint(const X & x, Y& y) const noexcept {
395  decltype(auto) t1 = smart_gpu_compute_hint(x, y);
396 
397  auto t2 = force_temporary_gpu_dim_only(t1);
398 
399  T alpha(1);
400  impl::egblas::bernoulli_sample_states(etl::size(y), alpha, t1.gpu_memory(), 1, t2.gpu_memory(), 1, *states);
401 
402  return t2;
403  }
410  template <typename X, typename Y>
411  Y& gpu_compute(const X & x, Y& y) const noexcept {
412  decltype(auto) t1 = select_smart_gpu_compute(x, y);
413 
414  T alpha(1);
415  impl::egblas::bernoulli_sample_states(etl::size(y), alpha, t1.gpu_memory(), 1, y.gpu_memory(), 1, *states);
416 
417  y.validate_gpu();
418  y.invalidate_cpu();
419 
420  return y;
421  }
422 
427  static std::string desc() noexcept {
428  return "bernoulli";
429  }
430 };
431 
436 template <typename T>
438  static constexpr bool linear = true;
439  static constexpr bool thread_safe = false;
440 
446  template <vector_mode_t V>
447  static constexpr bool vectorizable = false;
448 
452  template <typename E>
453  static constexpr bool gpu_computable = false;
454 
460  static T apply(const T& x) {
461  static random_engine rand_engine(std::time(nullptr));
462  static std::uniform_real_distribution<double> distribution(0.0, 1.0);
463 
464  return x > distribution(rand_engine) ? 0.0 : 1.0;
465  }
466 
471  static std::string desc() noexcept {
472  return "bernoulli_reverse";
473  }
474 };
475 
480 template <typename G, typename T>
482  static constexpr bool linear = true;
483  static constexpr bool thread_safe = false;
484 
485 private:
486  G& rand_engine;
487 
488 public:
492  explicit reverse_bernoulli_unary_g_op(G& rand_engine) : rand_engine(rand_engine) {
493  //Nothing else to init
494  }
495 
501  template <vector_mode_t V>
502  static constexpr bool vectorizable = false;
503 
507  template <typename E>
508  static constexpr bool gpu_computable = false;
509 
515  T apply(const T& x) const {
516  std::uniform_real_distribution<double> distribution(0.0, 1.0);
517 
518  return x > distribution(rand_engine) ? 0.0 : 1.0;
519  }
520 
525  static std::string desc() noexcept {
526  return "bernoulli_reverse";
527  }
528 };
529 
530 } //end of namespace etl
Unary operation sampling with a reverse Bernoulli distribution.
Definition: bernoulli.hpp:437
state_bernoulli_unary_g_op(G &rand_engine, const std::shared_ptr< void *> &states)
Construct a new state_bernoulli_unary_g_op.
Definition: bernoulli.hpp:364
T apply(const T &x) const
Apply the unary operator on x.
Definition: bernoulli.hpp:515
static T apply(const T &x)
Apply the unary operator on x.
Definition: bernoulli.hpp:460
Unary operation sampling with a Bernoulli distribution.
Definition: bernoulli.hpp:118
static auto gpu_compute_hint(const X &x, Y &y) noexcept
Compute the result of the operation using the GPU.
Definition: bernoulli.hpp:66
Y & gpu_compute(const X &x, Y &y) const noexcept
Compute the result of the operation using the GPU.
Definition: bernoulli.hpp:411
auto gpu_compute_hint(const X &x, Y &y) const noexcept
Compute the result of the operation using the GPU.
Definition: bernoulli.hpp:394
state_bernoulli_unary_g_op(G &rand_engine)
Construct a new state_bernoulli_unary_g_op.
Definition: bernoulli.hpp:352
static std::string desc() noexcept
Returns a textual representation of the operator.
Definition: bernoulli.hpp:525
decltype(auto) select_smart_gpu_compute(X &x, Y &y)
Compute the expression into a representation that is GPU up to date and possibly store this represent...
Definition: helpers.hpp:434
bernoulli_unary_g_op(G &rand_engine)
Construct a new bernoulli_unary_g_op.
Definition: bernoulli.hpp:129
static constexpr bool linear
Indicates if the operator is linear.
Definition: bernoulli.hpp:20
T apply(const T &x) const
Apply the unary operator on x.
Definition: bernoulli.hpp:153
EGBLAS wrappers for the bernoulli_sample operation.
static std::string desc() noexcept
Returns a textual representation of the operator.
Definition: bernoulli.hpp:315
static constexpr bool thread_safe
Indicates if the operator is thread safe or not.
Definition: bernoulli.hpp:21
static std::string desc() noexcept
Returns a textual representation of the operator.
Definition: bernoulli.hpp:205
Root namespace for the ETL library.
Definition: adapter.hpp:15
static constexpr bool vectorizable
Indicates if the expression is vectorizable using the given vector mode.
Definition: bernoulli.hpp:29
T apply(const T &x) const
Apply the unary operator on x.
Definition: bernoulli.hpp:268
Y & gpu_compute(const X &x, Y &y) const noexcept
Compute the result of the operation using the GPU.
Definition: bernoulli.hpp:187
state_bernoulli_unary_op(const std::shared_ptr< void *> states)
Construct a new operator.
Definition: bernoulli.hpp:252
Unary operation sampling with a reverse Bernoulli distribution.
Definition: bernoulli.hpp:481
T apply(const T &x) const
Apply the unary operator on x.
Definition: bernoulli.hpp:380
state_bernoulli_unary_op()
Construct a new operator.
Definition: bernoulli.hpp:242
static std::string desc() noexcept
Returns a textual representation of the operator.
Definition: bernoulli.hpp:471
decltype(auto) force_temporary_gpu_dim_only(E &&expr)
Force a temporary out of the expression, without copying its content.
Definition: temporary.hpp:223
static constexpr int complexity()
Estimate the complexity of operator.
Definition: bernoulli.hpp:42
auto gpu_compute_hint(const X &x, Y &y) const noexcept
Compute the result of the operation using the GPU.
Definition: bernoulli.hpp:167
constexpr size_t size(const E &expr) noexcept
Returns the size of the given ETL expression.
Definition: helpers.hpp:108
Unary operation sampling with a Bernoulli distribution.
Definition: bernoulli.hpp:19
Unary operation sampling with a Bernoulli distribution.
Definition: bernoulli.hpp:325
auto gpu_compute_hint(const X &x, Y &y) const noexcept
Compute the result of the operation using the GPU.
Definition: bernoulli.hpp:282
Unary operation sampling with a Bernoulli distribution.
Definition: bernoulli.hpp:215
static Y & gpu_compute(const X &x, Y &y) noexcept
Compute the result of the operation using the GPU.
Definition: bernoulli.hpp:88
static T apply(const T &x)
Apply the unary operator on x.
Definition: bernoulli.hpp:51
Y & gpu_compute(const X &x, Y &y) const noexcept
Compute the result of the operation using the GPU.
Definition: bernoulli.hpp:299
static constexpr bool gpu_computable
Indicates if the operator can be computed on GPU.
Definition: bernoulli.hpp:35
reverse_bernoulli_unary_g_op(G &rand_engine)
Construct a new reverse_bernoulli_unary_g_op.
Definition: bernoulli.hpp:492
std::mt19937_64 random_engine
The random engine used by the library.
Definition: random.hpp:22
static std::string desc() noexcept
Returns a textual representation of the operator.
Definition: bernoulli.hpp:108
static std::string desc() noexcept
Returns a textual representation of the operator.
Definition: bernoulli.hpp:427
decltype(auto) smart_gpu_compute_hint(E &expr, Y &y)
Compute the expression into a representation that is GPU up to date.
Definition: helpers.hpp:368