EigenRand  0.3.0
Basic.h
Go to the documentation of this file.
1 
12 #ifndef EIGENRAND_DISTS_BASIC_H
13 #define EIGENRAND_DISTS_BASIC_H
14 
15 namespace Eigen
16 {
17  namespace Rand
18  {
19  namespace constant
20  {
21  static constexpr double pi = 3.1415926535897932;
22  static constexpr double e = 2.7182818284590452;
23  }
24 
31  template<typename DerivedGen, typename Scalar>
32  class GenBase
33  {
34  public:
46  template<typename Derived, typename Urng>
47  inline const CwiseNullaryOp<internal::scalar_rng_adaptor<DerivedGen&, Scalar, Urng>, const Derived>
48  generate(Index rows, Index cols, Urng&& urng)
49  {
50  return {
51  rows, cols, { std::forward<Urng>(urng), static_cast<DerivedGen&>(*this) }
52  };
53  }
54 
65  template<typename Derived, typename Urng>
66  inline const CwiseNullaryOp<internal::scalar_rng_adaptor<DerivedGen&, Scalar, Urng>, const Derived>
67  generateLike(const Derived& o, Urng&& urng)
68  {
69  return {
70  o.rows(), o.cols(), { std::forward<Urng>(urng), static_cast<DerivedGen&>(*this) }
71  };
72  }
73  };
74 
82  template<typename DerivedGen, typename _Scalar, Index Dim>
84  {
85  public:
89  Index dims() const { return static_cast<DerivedGen&>(*this).dims(); }
90 
100  template<typename Urng>
101  inline Matrix<_Scalar, Dim, -1> generate(Urng&& urng, Index samples)
102  {
103  return static_cast<DerivedGen&>(*this).generatr(std::forward<Urng>(urng), samples);
104  }
105 
113  template<typename Urng>
114  inline Matrix<_Scalar, Dim, 1> generate(Urng&& urng)
115  {
116  return static_cast<DerivedGen&>(*this).generatr(std::forward<Urng>(urng));
117  }
118  };
119 
127  template<typename DerivedGen, typename _Scalar, Index Dim>
129  {
130  public:
134  Index dims() const { return static_cast<DerivedGen&>(*this).dims(); }
135 
145  template<typename Urng>
146  inline Matrix<_Scalar, Dim, -1> generate(Urng&& urng, Index samples)
147  {
148  return static_cast<DerivedGen&>(*this).generate(std::forward<Urng>(urng), samples);
149  }
150 
158  template<typename Urng>
159  inline Matrix<_Scalar, Dim, Dim> generate(Urng&& urng)
160  {
161  return static_cast<DerivedGen&>(*this).generate(std::forward<Urng>(urng));
162  }
163  };
164 
165  template<Index _alignment=0>
166  class CacheStore
167  {
168  protected:
169  enum { max_size = sizeof(internal::find_best_packet<float, -1>::type) };
170  int8_t raw_data[max_size + _alignment - 1] = { 0, };
171  void* aligned_ptr;
172 
173  public:
174  CacheStore()
175  {
176  aligned_ptr = (void*)((((size_t)raw_data + _alignment - 1) / _alignment) * _alignment);
177  }
178 
179  CacheStore(const CacheStore& c)
180  {
181  std::copy(c.raw_data, c.raw_data + max_size, raw_data);
182  aligned_ptr = (void*)((((size_t)raw_data + _alignment - 1) / _alignment) * _alignment);
183  }
184 
185  CacheStore(CacheStore&& c)
186  {
187  std::copy(c.raw_data, c.raw_data + max_size, raw_data);
188  aligned_ptr = (void*)((((size_t)raw_data + _alignment - 1) / _alignment) * _alignment);
189  }
190 
191  template<typename Ty>
192  Ty& get()
193  {
194  return *(Ty*)aligned_ptr;
195  }
196 
197  template<typename Ty>
198  const Ty& get() const
199  {
200  return *(const Ty*)aligned_ptr;
201  }
202  };
203 
204  template<>
205  class CacheStore<0>
206  {
207  protected:
208  enum { max_size = sizeof(internal::find_best_packet<float, -1>::type) };
209  int8_t raw_data[max_size] = { 0, };
210 
211  public:
212  CacheStore()
213  {
214  }
215 
216  CacheStore(const CacheStore& c)
217  {
218  std::copy(c.raw_data, c.raw_data + max_size, raw_data);
219  }
220 
221  CacheStore(CacheStore&& c)
222  {
223  std::copy(c.raw_data, c.raw_data + max_size, raw_data);
224  }
225 
226  template<typename Ty>
227  Ty& get()
228  {
229  return *(Ty*)raw_data;
230  }
231 
232  template<typename Ty>
233  const Ty& get() const
234  {
235  return *(const Ty*)raw_data;
236  }
237  };
238 
239  using OptCacheStore = CacheStore<EIGEN_MAX_ALIGN_BYTES>;
240 
246  template<typename _Scalar>
247  class RandbitsGen : public GenBase<RandbitsGen<_Scalar>, _Scalar>
248  {
249  static_assert(std::is_integral<_Scalar>::value, "randBits needs integral types.");
250 
251  public:
252  using Scalar = _Scalar;
253 
254  template<typename Rng>
255  EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
256  {
257  using namespace Eigen::internal;
258  return pfirst(std::forward<Rng>(rng)());
259  }
260 
261  template<typename Packet, typename Rng>
262  EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
263  {
264  using namespace Eigen::internal;
265  using RUtils = RawbitsMaker<Packet, Rng>;
266  return RUtils{}.rawbits(std::forward<Rng>(rng));
267  }
268  };
269 
275  template<typename _Scalar>
276  class BalancedGen : public GenBase<BalancedGen<_Scalar>, _Scalar>
277  {
278  static_assert(std::is_floating_point<_Scalar>::value, "balanced needs floating point types.");
279 
280  public:
281  using Scalar = _Scalar;
282 
283  template<typename Rng>
284  EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
285  {
286  using namespace Eigen::internal;
287  return ((_Scalar)((int32_t)pfirst(std::forward<Rng>(rng)()) & 0x7FFFFFFF) / 0x7FFFFFFF) * 2 - 1;
288  }
289 
290  template<typename Packet, typename Rng>
291  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
292  {
293  using namespace Eigen::internal;
294  using RUtils = RandUtils<Packet, Rng>;
295  return RUtils{}.balanced(std::forward<Rng>(rng));
296  }
297  };
298 
304  template<typename _Scalar>
305  class UniformRealGen : public GenBase<UniformRealGen<_Scalar>, _Scalar>
306  {
307  static_assert(std::is_floating_point<_Scalar>::value, "uniformReal needs floating point types.");
308 
309  public:
310  using Scalar = _Scalar;
311 
312  template<typename Rng>
313  EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
314  {
315  using namespace Eigen::internal;
316  return bit_scalar<_Scalar>{}.to_ur(pfirst(std::forward<Rng>(rng)()));
317  }
318 
319  template<typename Rng>
320  EIGEN_STRONG_INLINE const _Scalar nzur_scalar(Rng&& rng)
321  {
322  using namespace Eigen::internal;
323  return bit_scalar<_Scalar>{}.to_nzur(pfirst(std::forward<Rng>(rng)()));
324  }
325 
326  template<typename Packet, typename Rng>
327  EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
328  {
329  using namespace Eigen::internal;
330  using RUtils = RandUtils<Packet, Rng>;
331  return RUtils{}.uniform_real(std::forward<Rng>(rng));
332  }
333  };
334 
335 
341  template<typename _Scalar>
342  class BernoulliGen : public GenBase<BernoulliGen<_Scalar>, _Scalar>
343  {
344  uint32_t p;
345  public:
346  using Scalar = _Scalar;
347 
348  BernoulliGen(double _p = 0.5)
349  {
350  eigen_assert(0 <= _p && _p <= 1 );
351  p = (uint32_t)(_p * 0x80000000);
352  }
353 
354  BernoulliGen(const BernoulliGen&) = default;
355  BernoulliGen(BernoulliGen&&) = default;
356 
357  BernoulliGen& operator=(const BernoulliGen&) = default;
358  BernoulliGen& operator=(BernoulliGen&&) = default;
359 
360  template<typename Rng>
361  EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
362  {
363  using namespace Eigen::internal;
364  return (((uint32_t)pfirst(std::forward<Rng>(rng)()) & 0x7FFFFFFF) < p) ? 1 : 0;
365  }
366 
367  template<typename Packet, typename Rng>
368  EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
369  {
370  using namespace Eigen::internal;
371  using IPacket = decltype(reinterpret_to_int(std::declval<Packet>()));
372  using RUtils = RawbitsMaker<IPacket, Rng>;
373  auto one = pset1<Packet>(1);
374  auto zero = pset1<Packet>(0);
375  auto r = RUtils{}.rawbits(std::forward<Rng>(rng));
376  r = pand(r, pset1<IPacket>(0x7FFFFFFF));
377  return pblendv(pcmplt(r, pset1<IPacket>(p)), one, zero);
378  }
379  };
380 
381 
382  template<typename Derived, typename Urng>
383  using RandBitsType = CwiseNullaryOp<internal::scalar_rng_adaptor<RandbitsGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
384 
397  template<typename Derived, typename Urng>
398  inline const RandBitsType<Derived, Urng>
399  randBits(Index rows, Index cols, Urng&& urng)
400  {
401  return {
402  rows, cols, { std::forward<Urng>(urng) }
403  };
404  }
405 
417  template<typename Derived, typename Urng>
418  inline const RandBitsType<Derived, Urng>
419  randBitsLike(Derived& o, Urng&& urng)
420  {
421  return {
422  o.rows(), o.cols(), { std::forward<Urng>(urng) }
423  };
424  }
425 
426  template<typename Derived, typename Urng>
427  using BalancedType = CwiseNullaryOp<internal::scalar_rng_adaptor<BalancedGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
428 
441  template<typename Derived, typename Urng>
442  inline const BalancedType<Derived, Urng>
443  balanced(Index rows, Index cols, Urng&& urng)
444  {
445  return {
446  rows, cols, { std::forward<Urng>(urng) }
447  };
448  }
449 
461  template<typename Derived, typename Urng>
462  inline const BalancedType<Derived, Urng>
463  balancedLike(const Derived& o, Urng&& urng)
464  {
465  return {
466  o.rows(), o.cols(), { std::forward<Urng>(urng) }
467  };
468  }
469 
470  template<typename Derived, typename Urng>
471  using UniformRealType = CwiseNullaryOp<internal::scalar_rng_adaptor<UniformRealGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
472 
485  template<typename Derived, typename Urng>
486  inline const UniformRealType<Derived, Urng>
487  uniformReal(Index rows, Index cols, Urng&& urng)
488  {
489  return {
490  rows, cols, { std::forward<Urng>(urng) }
491  };
492  }
493 
505  template<typename Derived, typename Urng>
506  inline const UniformRealType<Derived, Urng>
507  uniformRealLike(Derived& o, Urng&& urng)
508  {
509  return {
510  o.rows(), o.cols(), { std::forward<Urng>(urng) }
511  };
512  }
513 
514  template<typename Derived, typename Urng>
515  using BernoulliType = CwiseNullaryOp<internal::scalar_rng_adaptor<BernoulliGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
516 
528  template<typename Derived, typename Urng>
529  inline const BernoulliType<Derived, Urng>
530  bernoulli(Index rows, Index cols, Urng&& urng, double p = 0.5)
531  {
532  return {
533  rows, cols, { std::forward<Urng>(urng), BernoulliGen<typename Derived::Scalar>{ p } }
534  };
535  }
536 
547  template<typename Derived, typename Urng>
548  inline const BernoulliType<Derived, Urng>
549  bernoulli(Derived& o, Urng&& urng, double p = 0.5)
550  {
551  return {
552  o.rows(), o.cols(), { std::forward<Urng>(urng), BernoulliGen<typename Derived::Scalar>{ p } }
553  };
554  }
555  }
556 }
557 
558 #endif
Generator of reals in a range [-1, 1]
Definition: Basic.h:277
Generator of Bernoulli distribution.
Definition: Basic.h:343
Base class of all univariate random generators.
Definition: Basic.h:33
const CwiseNullaryOp< internal::scalar_rng_adaptor< DerivedGen &, Scalar, Urng >, const Derived > generate(Index rows, Index cols, Urng &&urng)
generate random values from its distribution
Definition: Basic.h:48
const CwiseNullaryOp< internal::scalar_rng_adaptor< DerivedGen &, Scalar, Urng >, const Derived > generateLike(const Derived &o, Urng &&urng)
generate random values from its distribution
Definition: Basic.h:67
Base class of all multivariate random matrix generators.
Definition: Basic.h:129
Matrix< _Scalar, Dim, -1 > generate(Urng &&urng, Index samples)
generates multiple samples at once
Definition: Basic.h:146
Matrix< _Scalar, Dim, Dim > generate(Urng &&urng)
generates one sample
Definition: Basic.h:159
Index dims() const
returns the dimensions of matrices to be generated
Definition: Basic.h:134
Base class of all multivariate random vector generators.
Definition: Basic.h:84
Matrix< _Scalar, Dim, -1 > generate(Urng &&urng, Index samples)
generates multiple samples at once
Definition: Basic.h:101
Index dims() const
returns the dimensions of vectors to be generated
Definition: Basic.h:89
Matrix< _Scalar, Dim, 1 > generate(Urng &&urng)
generates one sample
Definition: Basic.h:114
Generator of random bits for integral scalars.
Definition: Basic.h:248
Generator of reals in a range [0, 1)
Definition: Basic.h:306
const RandBitsType< Derived, Urng > randBits(Index rows, Index cols, Urng &&urng)
generates integers with random bits
Definition: Basic.h:399
const BernoulliType< Derived, Urng > bernoulli(Index rows, Index cols, Urng &&urng, double p=0.5)
generates 1 with probability p and 0 with probability 1 - p
Definition: Basic.h:530
const BalancedType< Derived, Urng > balanced(Index rows, Index cols, Urng &&urng)
generates reals in a range [-1, 1]
Definition: Basic.h:443
const UniformRealType< Derived, Urng > uniformReal(Index rows, Index cols, Urng &&urng)
generates reals in a range [0, 1)
Definition: Basic.h:487
const UniformRealType< Derived, Urng > uniformRealLike(Derived &o, Urng &&urng)
generates reals in a range [0, 1)
Definition: Basic.h:507
const BalancedType< Derived, Urng > balancedLike(const Derived &o, Urng &&urng)
generates reals in a range [-1, 1]
Definition: Basic.h:463
const RandBitsType< Derived, Urng > randBitsLike(Derived &o, Urng &&urng)
generates integers with random bits
Definition: Basic.h:419