EigenRand  0.4.0-alpha
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 
241  template<typename _Scalar>
242  struct ExtractFirstUint;
243 
244  template<>
245  struct ExtractFirstUint<float>
246  {
247  template<typename Packet>
248  auto operator()(Packet v) -> decltype(Eigen::internal::pfirst(v))
249  {
250  return Eigen::internal::pfirst(v);
251  }
252  };
253 
254  template<>
255  struct ExtractFirstUint<double>
256  {
257  template<typename Packet>
258  auto operator()(Packet v) -> uint64_t
259  {
260  uint64_t arr[sizeof(Packet) / 8];
261  Eigen::internal::pstoreu((Packet*)arr, v);
262  return arr[0];
263  }
264  };
265 
271  template<typename _Scalar>
272  class RandbitsGen : public GenBase<RandbitsGen<_Scalar>, _Scalar>
273  {
274  static_assert(std::is_integral<_Scalar>::value, "randBits needs integral types.");
275 
276  public:
277  using Scalar = _Scalar;
278 
279  template<typename Rng>
280  EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
281  {
282  using namespace Eigen::internal;
283  return pfirst(std::forward<Rng>(rng)());
284  }
285 
286  template<typename Packet, typename Rng>
287  EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
288  {
289  using namespace Eigen::internal;
290  using RUtils = RawbitsMaker<Packet, Rng>;
291  return RUtils{}.rawbits(std::forward<Rng>(rng));
292  }
293  };
294 
300  template<typename _Scalar>
301  class BalancedGen : public GenBase<BalancedGen<_Scalar>, _Scalar>
302  {
303  static_assert(std::is_floating_point<_Scalar>::value, "balanced needs floating point types.");
304 
305  public:
306  using Scalar = _Scalar;
307 
308  template<typename Rng>
309  EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
310  {
311  using namespace Eigen::internal;
312  return ((_Scalar)((int32_t)pfirst(std::forward<Rng>(rng)()) & 0x7FFFFFFF) / 0x7FFFFFFF) * 2 - 1;
313  }
314 
315  template<typename Packet, typename Rng>
316  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
317  {
318  using namespace Eigen::internal;
319  using RUtils = RandUtils<Packet, Rng>;
320  return RUtils{}.balanced(std::forward<Rng>(rng));
321  }
322  };
323 
329  template<typename _Scalar>
330  class Balanced2Gen : public GenBase<Balanced2Gen<_Scalar>, _Scalar>
331  {
332  static_assert(std::is_floating_point<_Scalar>::value, "balanced needs floating point types.");
333  _Scalar slope = 2, bias = -1;
334  public:
335  using Scalar = _Scalar;
336 
342  Balanced2Gen(_Scalar _a = -1, _Scalar _b = 1)
343  : slope{ _b - _a }, bias{ _a }
344  {
345  }
346 
347  template<typename Rng>
348  EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
349  {
350  using namespace Eigen::internal;
351  return ((_Scalar)((int32_t)pfirst(std::forward<Rng>(rng)()) & 0x7FFFFFFF) / 0x7FFFFFFF) * slope + bias;
352  }
353 
354  template<typename Packet, typename Rng>
355  EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
356  {
357  using namespace Eigen::internal;
358  using RUtils = RandUtils<Packet, Rng>;
359  return RUtils{}.balanced(std::forward<Rng>(rng), slope, bias);
360  }
361  };
362 
368  template<typename _Scalar>
369  class StdUniformRealGen : public GenBase<StdUniformRealGen<_Scalar>, _Scalar>
370  {
371  static_assert(std::is_floating_point<_Scalar>::value, "uniformReal needs floating point types.");
372 
373  public:
374  using Scalar = _Scalar;
375 
376  template<typename Rng>
377  EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
378  {
379  using namespace Eigen::internal;
380  return BitScalar<_Scalar>{}.to_ur(ExtractFirstUint<_Scalar>{}(std::forward<Rng>(rng)()));
381  }
382 
383  template<typename Rng>
384  EIGEN_STRONG_INLINE const _Scalar nzur_scalar(Rng&& rng)
385  {
386  using namespace Eigen::internal;
387  return BitScalar<_Scalar>{}.to_nzur(ExtractFirstUint<_Scalar>{}(std::forward<Rng>(rng)()));
388  }
389 
390  template<typename Packet, typename Rng>
391  EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
392  {
393  using namespace Eigen::internal;
394  using RUtils = RandUtils<Packet, Rng>;
395  return RUtils{}.uniform_real(std::forward<Rng>(rng));
396  }
397  };
398 
404  template<typename _Scalar>
405  class UniformRealGen : public GenBase<UniformRealGen<_Scalar>, _Scalar>
406  {
407  static_assert(std::is_floating_point<_Scalar>::value, "uniformReal needs floating point types.");
408  _Scalar bias, slope;
409 
410  public:
411  using Scalar = _Scalar;
412 
413  UniformRealGen(_Scalar _min = 0, _Scalar _max = 1)
414  : bias{ _min }, slope{ _max - _min }
415  {
416  }
417 
418  UniformRealGen(const UniformRealGen&) = default;
419  UniformRealGen(UniformRealGen&&) = default;
420 
421  UniformRealGen& operator=(const UniformRealGen&) = default;
422  UniformRealGen& operator=(UniformRealGen&&) = default;
423 
424  template<typename Rng>
425  EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
426  {
427  using namespace Eigen::internal;
428  return bias + BitScalar<_Scalar>{}.to_ur(pfirst(std::forward<Rng>(rng)())) * slope;
429  }
430 
431  template<typename Packet, typename Rng>
432  EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
433  {
434  using namespace Eigen::internal;
435  using RUtils = RandUtils<Packet, Rng>;
436  return padd(pmul(
437  RUtils{}.uniform_real(std::forward<Rng>(rng)), pset1<Packet>(slope)
438  ), pset1<Packet>(bias));
439  }
440  };
441 
442 
448  template<typename _Scalar>
449  class BernoulliGen : public GenBase<BernoulliGen<_Scalar>, _Scalar>
450  {
451  uint32_t p;
452  public:
453  using Scalar = _Scalar;
454 
455  BernoulliGen(double _p = 0.5)
456  {
457  eigen_assert(0 <= _p && _p <= 1 );
458  p = (uint32_t)(_p * 0x80000000);
459  }
460 
461  BernoulliGen(const BernoulliGen&) = default;
462  BernoulliGen(BernoulliGen&&) = default;
463 
464  BernoulliGen& operator=(const BernoulliGen&) = default;
465  BernoulliGen& operator=(BernoulliGen&&) = default;
466 
467  template<typename Rng>
468  EIGEN_STRONG_INLINE const _Scalar operator() (Rng&& rng)
469  {
470  using namespace Eigen::internal;
471  return (((uint32_t)pfirst(std::forward<Rng>(rng)()) & 0x7FFFFFFF) < p) ? 1 : 0;
472  }
473 
474  template<typename Packet, typename Rng>
475  EIGEN_STRONG_INLINE const Packet packetOp(Rng&& rng)
476  {
477  using namespace Eigen::internal;
478  using IPacket = decltype(reinterpret_to_int(std::declval<Packet>()));
479  using RUtils = RawbitsMaker<IPacket, Rng>;
480  auto one = pset1<Packet>(1);
481  auto zero = pset1<Packet>(0);
482  auto r = RUtils{}.rawbits(std::forward<Rng>(rng));
483  r = pand(r, pset1<IPacket>(0x7FFFFFFF));
484  return pblendv(pcmplt(r, pset1<IPacket>(p)), one, zero);
485  }
486  };
487 
488 
489  template<typename Derived, typename Urng>
490  using RandBitsType = CwiseNullaryOp<internal::scalar_rng_adaptor<RandbitsGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
491 
504  template<typename Derived, typename Urng>
505  inline const RandBitsType<Derived, Urng>
506  randBits(Index rows, Index cols, Urng&& urng)
507  {
508  return {
509  rows, cols, { std::forward<Urng>(urng) }
510  };
511  }
512 
524  template<typename Derived, typename Urng>
525  inline const RandBitsType<Derived, Urng>
526  randBitsLike(Derived& o, Urng&& urng)
527  {
528  return {
529  o.rows(), o.cols(), { std::forward<Urng>(urng) }
530  };
531  }
532 
533  template<typename Derived, typename Urng>
534  using BalancedType = CwiseNullaryOp<internal::scalar_rng_adaptor<BalancedGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
535 
548  template<typename Derived, typename Urng>
549  inline const BalancedType<Derived, Urng>
550  balanced(Index rows, Index cols, Urng&& urng)
551  {
552  return {
553  rows, cols, { std::forward<Urng>(urng) }
554  };
555  }
556 
568  template<typename Derived, typename Urng>
569  inline const BalancedType<Derived, Urng>
570  balancedLike(const Derived& o, Urng&& urng)
571  {
572  return {
573  o.rows(), o.cols(), { std::forward<Urng>(urng) }
574  };
575  }
576 
577  template<typename Derived, typename Urng>
578  using Balanced2Type = CwiseNullaryOp<internal::scalar_rng_adaptor<Balanced2Gen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
579 
593  template<typename Derived, typename Urng>
594  inline const Balanced2Type<Derived, Urng>
595  balanced(Index rows, Index cols, Urng&& urng, typename Derived::Scalar a, typename Derived::Scalar b)
596  {
597  return {
598  rows, cols, { std::forward<Urng>(urng), Balanced2Gen<typename Derived::Scalar>{a, b} }
599  };
600  }
601 
614  template<typename Derived, typename Urng>
615  inline const Balanced2Type<Derived, Urng>
616  balancedLike(const Derived& o, Urng&& urng, typename Derived::Scalar a, typename Derived::Scalar b)
617  {
618  return {
619  o.rows(), o.cols(), { std::forward<Urng>(urng), Balanced2Gen<typename Derived::Scalar>{a, b} }
620  };
621  }
622 
623  template<typename Derived, typename Urng>
624  using StdUniformRealType = CwiseNullaryOp<internal::scalar_rng_adaptor<StdUniformRealGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
625 
638  template<typename Derived, typename Urng>
639  inline const StdUniformRealType<Derived, Urng>
640  uniformReal(Index rows, Index cols, Urng&& urng)
641  {
642  return {
643  rows, cols, { std::forward<Urng>(urng) }
644  };
645  }
646 
658  template<typename Derived, typename Urng>
659  inline const StdUniformRealType<Derived, Urng>
660  uniformRealLike(Derived& o, Urng&& urng)
661  {
662  return {
663  o.rows(), o.cols(), { std::forward<Urng>(urng) }
664  };
665  }
666 
667  template<typename Derived, typename Urng>
668  using UniformRealType = CwiseNullaryOp<internal::scalar_rng_adaptor<UniformRealGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
669 
683  template<typename Derived, typename Urng>
684  inline const UniformRealType<Derived, Urng>
685  uniformReal(Index rows, Index cols, Urng&& urng, typename Derived::Scalar min, typename Derived::Scalar max)
686  {
687  return {
688  rows, cols, { std::forward<Urng>(urng), UniformRealGen<typename Derived::Scalar>{ min, max } }
689  };
690  }
691 
704  template<typename Derived, typename Urng>
705  inline const UniformRealType<Derived, Urng>
706  uniformRealLike(Derived& o, Urng&& urng, typename Derived::Scalar min, typename Derived::Scalar max)
707  {
708  return {
709  o.rows(), o.cols(), { std::forward<Urng>(urng), UniformRealGen<typename Derived::Scalar>{ min, max } }
710  };
711  }
712 
713  template<typename Derived, typename Urng>
714  using BernoulliType = CwiseNullaryOp<internal::scalar_rng_adaptor<BernoulliGen<typename Derived::Scalar>, typename Derived::Scalar, Urng, true>, const Derived>;
715 
727  template<typename Derived, typename Urng>
728  inline const BernoulliType<Derived, Urng>
729  bernoulli(Index rows, Index cols, Urng&& urng, double p = 0.5)
730  {
731  return {
732  rows, cols, { std::forward<Urng>(urng), BernoulliGen<typename Derived::Scalar>{ p } }
733  };
734  }
735 
746  template<typename Derived, typename Urng>
747  inline const BernoulliType<Derived, Urng>
748  bernoulli(Derived& o, Urng&& urng, double p = 0.5)
749  {
750  return {
751  o.rows(), o.cols(), { std::forward<Urng>(urng), BernoulliGen<typename Derived::Scalar>{ p } }
752  };
753  }
754  }
755 }
756 
757 #endif
Generator of reals in a range [a, b]
Definition: Basic.h:331
Balanced2Gen(_Scalar _a=-1, _Scalar _b=1)
Construct a new balanced generator.
Definition: Basic.h:342
Generator of reals in a range [-1, 1]
Definition: Basic.h:302
Generator of Bernoulli distribution.
Definition: Basic.h:450
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:273
Generator of reals in a range [0, 1)
Definition: Basic.h:370
Generator of reals in a range [a, b)
Definition: Basic.h:406
const StdUniformRealType< Derived, Urng > uniformReal(Index rows, Index cols, Urng &&urng)
generates reals in a range [0, 1)
Definition: Basic.h:640
const RandBitsType< Derived, Urng > randBits(Index rows, Index cols, Urng &&urng)
generates integers with random bits
Definition: Basic.h:506
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:729
const BalancedType< Derived, Urng > balanced(Index rows, Index cols, Urng &&urng)
generates reals in a range [-1, 1]
Definition: Basic.h:550
const BalancedType< Derived, Urng > balancedLike(const Derived &o, Urng &&urng)
generates reals in a range [-1, 1]
Definition: Basic.h:570
const StdUniformRealType< Derived, Urng > uniformRealLike(Derived &o, Urng &&urng)
generates reals in a range [0, 1)
Definition: Basic.h:660
const RandBitsType< Derived, Urng > randBitsLike(Derived &o, Urng &&urng)
generates integers with random bits
Definition: Basic.h:526