vSMC  v3.0.0
Scalable Monte Carlo
mkl.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/rng/mkl.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2016, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef VSMC_RNG_MKL_HPP
33 #define VSMC_RNG_MKL_HPP
34 
37 
38 #define VSMC_RUNTIME_WARNING_RNG_MKL_OFFSET \
39  VSMC_RUNTIME_WARNING((offset < MaxOffset), \
40  "**MKLEngine** EXCESS MAXIMUM NUMBER OF INDEPDENT RNG STREAMS")
41 
42 #define VSMC_RUNTIME_ASSERT_RNG_MKL_DISCARD \
43  VSMC_RUNTIME_ASSERT( \
44  (nskip >= 0), "**MKLEngine::discard** INPUT IS NEGATIVE")
45 
46 namespace vsmc
47 {
48 
49 namespace internal
50 {
51 
52 #if VSMC_NO_RUNTIME_ASSERT
53 inline int mkl_error_check(int status, const char *, const char *)
54 {
55  return status;
56 }
57 #else // VSMC_NO_RUNTIME_ASSERT
58 inline int mkl_error_check(int status, const char *cpp, const char *c)
59 {
60  if (status == VSL_ERROR_OK)
61  return status;
62 
63  std::string msg;
64  msg += "**";
65  msg += cpp;
66  msg += "**";
67  msg += " failed";
68  msg += "; MKL function: ";
69  msg += c;
70  msg += "; Error code: ";
71  msg += std::to_string(status);
72 
73  VSMC_RUNTIME_ASSERT((status == VSL_ERROR_OK), msg.c_str());
74 
75  return status;
76 }
77 #endif // VSMC_NO_RUNTIME_ASSERT
78 
79 } // namespace vsmc::internal
80 
83 class MKLStream
84 {
85  public:
86  explicit MKLStream(::VSLStreamStatePtr ptr = nullptr) : ptr_(nullptr)
87  {
88  reset(ptr);
89  }
90 
92  MKLStream(MKL_INT brng, MKL_UINT seed) : ptr_(nullptr)
93  {
94  reset(brng, seed);
95  }
96 
98  MKLStream(MKL_INT brng, MKL_INT n, unsigned *params) : ptr_(nullptr)
99  {
100  reset(brng, n, params);
101  }
102 
104  MKLStream(const MKLStream &other)
105  {
106  ::VSLStreamStatePtr ptr = nullptr;
107  if (internal::mkl_error_check(::vslCopyStream(&ptr, other.ptr_),
108  "MKLStream::MKLStream", "::vslCopyStream") == VSL_ERROR_OK) {
109  reset(ptr);
110  }
111  }
112 
115  {
116  if (this != &other) {
117  ::VSLStreamStatePtr ptr = nullptr;
118  if (internal::mkl_error_check(::vslCopyStream(&ptr, other.ptr_),
119  "MKLStream::operator=",
120  "::vslCopyStream") == VSL_ERROR_OK) {
121  reset(ptr);
122  }
123  }
124 
125  return *this;
126  }
127 
128  MKLStream(MKLStream &&other) : ptr_(other.ptr_) { other.ptr_ = nullptr; }
129 
131  {
132  if (this != &other) {
133  release();
134  ptr_ = other.ptr_;
135  other.ptr_ = nullptr;
136  }
137 
138  return *this;
139  }
140 
142  ~MKLStream() { release(); }
143 
144  int reset(::VSLStreamStatePtr ptr)
145  {
146  int status = release();
147  ptr_ = ptr;
148 
149  return status;
150  }
151 
153  int reset(MKL_INT brng, MKL_UINT seed)
154  {
155  ::VSLStreamStatePtr ptr = nullptr;
156  int status =
157  internal::mkl_error_check(::vslNewStream(&ptr, brng, seed),
158  "MKLStream::reset", "::vslNewStream");
159  if (status == VSL_ERROR_OK)
160  reset(ptr);
161 
162  return status;
163  }
164 
166  int reset(MKL_INT brng, MKL_INT n, unsigned *params)
167  {
168  ::VSLStreamStatePtr ptr = nullptr;
169  int status =
170  internal::mkl_error_check(::vslNewStreamEx(&ptr, brng, n, params),
171  "MKLStream::reset", "::vslNewStreamEx");
172  if (status == VSL_ERROR_OK)
173  reset(ptr);
174 
175  return status;
176  }
177 
179  int release()
180  {
181  if (ptr_ == nullptr)
182  return VSL_ERROR_OK;
183 
184  int status = internal::mkl_error_check(::vslDeleteStream(&ptr_),
185  "MKLStream::release", "::vslDeleteStream");
186  ptr_ = nullptr;
187 
188  return status;
189  }
190 
191  bool empty() const { return ptr_ == nullptr; }
192 
194  int save_f(const std::string &fname) const
195  {
196  return internal::mkl_error_check(::vslSaveStreamF(ptr_, fname.c_str()),
197  "MKLStream::save_f", "::vslSaveStreamF");
198  }
199 
201  int load_f(const std::string &fname)
202  {
203  ::VSLStreamStatePtr ptr = nullptr;
204  int status =
205  internal::mkl_error_check(::vslSaveStreamF(&ptr, fname.c_str()),
206  "MKLStream::load_f", "::vslSaveStreamF");
207  if (status == VSL_ERROR_OK)
208  reset(ptr);
209 
210  return status;
211  }
212 
214  int save_m(char *memptr) const
215  {
216  return internal::mkl_error_check(::vslSaveStreamM(ptr_, memptr),
217  "MKLStream::save_m", "::vslSaveStreamM");
218  }
219 
221  int load_m(const char *memptr)
222  {
223  ::VSLStreamStatePtr ptr = nullptr;
224  int status = internal::mkl_error_check(::vslLoadStreamM(&ptr, memptr),
225  "MKLStream::load_m", "::vslLoadStreamM");
226  if (status == VSL_ERROR_OK)
227  reset(ptr);
228 
229  return status;
230  }
231 
233  int get_size() const { return ::vslGetStreamSize(ptr_); }
234 
236  int leapfrog(MKL_INT k, MKL_INT nstreams)
237  {
239  ::vslLeapfrogStream(ptr_, k, nstreams), "MKLStream::leapfrog",
240  "::vslLeapfrogStream");
241  }
242 
244  int skip_ahead(long long nskip)
245  {
246  return internal::mkl_error_check(::vslSkipAheadStream(ptr_, nskip),
247  "MKLStream::skip_ahead", "::vslSkipAheadStream");
248  }
249 
251  int get_brng() const { return ::vslGetStreamStateBrng(ptr_); }
252 
254  static int get_num_reg_brngs() { return ::vslGetNumRegBrngs(); }
255 
258  MKL_INT brng, ::VSLBRngProperties *properties)
259  {
261  ::vslGetBrngProperties(brng, properties),
262  "MKLStream::get_brng_properties", "::vslGetBrngProperties");
263  }
264 
266  static bool has_leap_frog(MKL_INT brng)
267  {
268  MKLStream stream(brng, 1);
269 
270  return ::vslLeapfrogStream(stream.ptr_, 1, 2) == VSL_ERROR_OK;
271  }
272 
274  static bool has_skip_ahead(MKL_INT brng)
275  {
276  MKLStream stream(brng, 1);
277 
278  return ::vslSkipAheadStream(stream.ptr_, 1) == VSL_ERROR_OK;
279  }
280 
282  static bool has_uniform_bits32(
283  MKL_INT brng, MKL_INT method = VSL_RNG_METHOD_UNIFORMBITS32_STD)
284  {
285  MKLStream stream(brng, 1);
286  unsigned r;
287 
288  return ::viRngUniformBits32(method, stream.ptr_, 1, &r) ==
289  VSL_ERROR_OK;
290  }
291 
293  static bool has_uniform_bits64(
294  MKL_INT brng, MKL_INT method = VSL_RNG_METHOD_UNIFORMBITS64_STD)
295  {
296  MKLStream stream(brng, 1);
297  unsigned MKL_INT64 r;
298 
299  return ::viRngUniformBits64(method, stream.ptr_, 1, &r) ==
300  VSL_ERROR_OK;
301  }
302 
304  int uniform(MKL_INT n, float *r, float a, float b,
305  MKL_INT method = VSL_RNG_METHOD_UNIFORM_STD)
306  {
308  ::vsRngUniform(method, ptr_, n, r, a, b), "MKLStream::uniform",
309  "::vsRngUniform");
310  }
311 
313  int uniform(MKL_INT n, double *r, double a, double b,
314  MKL_INT method = VSL_RNG_METHOD_UNIFORM_STD)
315  {
317  ::vdRngUniform(method, ptr_, n, r, a, b), "MKLStream::uniform",
318  "::vdRngUniform");
319  }
320 
322  int gaussian(MKL_INT n, float *r, float a, float sigma,
323  MKL_INT method = VSL_RNG_METHOD_GAUSSIAN_BOXMULLER2)
324  {
326  ::vsRngGaussian(method, ptr_, n, r, a, sigma),
327  "MKLStream::gaussian", "::vsRngGaussian");
328  }
329 
331  int gaussian(MKL_INT n, double *r, double a, double sigma,
332  MKL_INT method = VSL_RNG_METHOD_GAUSSIAN_BOXMULLER2)
333  {
335  ::vdRngGaussian(method, ptr_, n, r, a, sigma),
336  "MKLStream::gaussian", "::vdRngGaussian");
337  }
338 
340  int gaussian_mv(MKL_INT n, float *r, MKL_INT dimen, MKL_INT mstorage,
341  const float *a, const float *t,
342  MKL_INT method = VSL_RNG_METHOD_GAUSSIANMV_BOXMULLER2)
343  {
345  ::vsRngGaussianMV(method, ptr_, n, r, dimen, mstorage, a, t),
346  "MKLStream::gaussian_mv", "::vsRngGaussianMV");
347  }
348 
350  int gaussian_mv(MKL_INT n, double *r, MKL_INT dimen, MKL_INT mstorage,
351  const double *a, const double *t,
352  MKL_INT method = VSL_RNG_METHOD_GAUSSIANMV_BOXMULLER2)
353  {
355  ::vdRngGaussianMV(method, ptr_, n, r, dimen, mstorage, a, t),
356  "MKLStream::gaussian_mv", "::vdRngGaussianMV");
357  }
358 
360  int exponential(MKL_INT n, float *r, float a, float beta,
361  MKL_INT method = VSL_RNG_METHOD_EXPONENTIAL_ICDF)
362  {
364  ::vsRngExponential(method, ptr_, n, r, a, beta),
365  "MKLStream::exponential", "::vsRngExponential");
366  }
367 
369  int exponential(MKL_INT n, double *r, double a, double beta,
370  MKL_INT method = VSL_RNG_METHOD_EXPONENTIAL_ICDF)
371  {
373  ::vdRngExponential(method, ptr_, n, r, a, beta),
374  "MKLStream::exponential", "::vdRngExponential");
375  }
376 
378  int laplace(MKL_INT n, float *r, float a, float beta,
379  MKL_INT method = VSL_RNG_METHOD_LAPLACE_ICDF)
380  {
382  ::vsRngLaplace(method, ptr_, n, r, a, beta), "MKLStream::laplace",
383  "::vsRngLaplace");
384  }
385 
387  int laplace(MKL_INT n, double *r, double a, double beta,
388  MKL_INT method = VSL_RNG_METHOD_LAPLACE_ICDF)
389  {
391  ::vdRngLaplace(method, ptr_, n, r, a, beta), "MKLStream::laplace",
392  "::vdRngLaplace");
393  }
394 
396  int weibull(MKL_INT n, float *r, float alpha, float a, float beta,
397  MKL_INT method = VSL_RNG_METHOD_WEIBULL_ICDF)
398  {
400  ::vsRngWeibull(method, ptr_, n, r, alpha, a, beta),
401  "MKLStream::weibull", "::vsRngWeibull");
402  }
403 
405  int weibull(MKL_INT n, double *r, double alpha, double a, double beta,
406  MKL_INT method = VSL_RNG_METHOD_WEIBULL_ICDF)
407  {
409  ::vdRngWeibull(method, ptr_, n, r, alpha, a, beta),
410  "MKLStream::weibull", "::vdRngWeibull");
411  }
412 
414  int cauchy(MKL_INT n, float *r, float a, float beta,
415  MKL_INT method = VSL_RNG_METHOD_CAUCHY_ICDF)
416  {
418  ::vsRngCauchy(method, ptr_, n, r, a, beta), "MKLStream::cauchy",
419  "::vsRngCauchy");
420  }
421 
423  int cauchy(MKL_INT n, double *r, double a, double beta,
424  MKL_INT method = VSL_RNG_METHOD_CAUCHY_ICDF)
425  {
427  ::vdRngCauchy(method, ptr_, n, r, a, beta), "MKLStream::cauchy",
428  "::vdRngCauchy");
429  }
430 
432  int rayleigh(MKL_INT n, float *r, float a, float beta,
433  MKL_INT method = VSL_RNG_METHOD_RAYLEIGH_ICDF)
434  {
436  ::vsRngRayleigh(method, ptr_, n, r, a, beta),
437  "MKLStream::rayleigh", "::vsRngRayleigh");
438  }
439 
441  int rayleigh(MKL_INT n, double *r, double a, double beta,
442  MKL_INT method = VSL_RNG_METHOD_RAYLEIGH_ICDF)
443  {
445  ::vdRngRayleigh(method, ptr_, n, r, a, beta),
446  "MKLStream::rayleigh", "::vdRngRayleigh");
447  }
448 
450  int lognormal(MKL_INT n, float *r, float a, float sigma, float b,
451  float beta, MKL_INT method = VSL_RNG_METHOD_LOGNORMAL_BOXMULLER2)
452  {
454  ::vsRngLognormal(method, ptr_, n, r, a, sigma, b, beta),
455  "MKLStream::lognormal", "::vsRngLognormal");
456  }
457 
459  int lognormal(MKL_INT n, double *r, double a, double sigma, double b,
460  double beta, MKL_INT method = VSL_RNG_METHOD_LOGNORMAL_BOXMULLER2)
461  {
463  ::vdRngLognormal(method, ptr_, n, r, a, sigma, b, beta),
464  "MKLStream::lognormal", "::vdRngLognormal");
465  }
466 
468  int gumbel(MKL_INT n, float *r, float a, float beta,
469  MKL_INT method = VSL_RNG_METHOD_GUMBEL_ICDF)
470  {
472  ::vsRngGumbel(method, ptr_, n, r, a, beta), "MKLStream::gumbel",
473  "::vsRngGumbel");
474  }
475 
477  int gumbel(MKL_INT n, double *r, double a, double beta,
478  MKL_INT method = VSL_RNG_METHOD_GUMBEL_ICDF)
479  {
481  ::vdRngGumbel(method, ptr_, n, r, a, beta), "MKLStream::gumbel",
482  "::vdRngGumbel");
483  }
484 
486  int gamma(MKL_INT n, float *r, float alpha, float a, float beta,
487  MKL_INT method = VSL_RNG_METHOD_GAMMA_GNORM)
488  {
490  ::vsRngGamma(method, ptr_, n, r, alpha, a, beta),
491  "MKLStream::gamma", "::vsRngGamma");
492  }
493 
495  int gamma(MKL_INT n, double *r, double alpha, double a, double beta,
496  MKL_INT method = VSL_RNG_METHOD_GAMMA_GNORM)
497  {
499  ::vdRngGamma(method, ptr_, n, r, alpha, a, beta),
500  "MKLStream::gamma", "::vdRngGamma");
501  }
502 
504  int beta(MKL_INT n, float *r, float p, float q, float a, float beta,
505  MKL_INT method = VSL_RNG_METHOD_BETA_CJA)
506  {
508  ::vsRngBeta(method, ptr_, n, r, p, q, a, beta), "MKLStream::beta",
509  "::vsRngBeta");
510  }
511 
513  int beta(MKL_INT n, double *r, double p, double q, double a, double beta,
514  MKL_INT method = VSL_RNG_METHOD_BETA_CJA)
515  {
517  ::vdRngBeta(method, ptr_, n, r, p, q, a, beta), "MKLStream::beta",
518  "::vdRngBeta");
519  }
520 
522  int uniform(MKL_INT n, int *r, int a, int b,
523  MKL_INT method = VSL_RNG_METHOD_UNIFORM_STD)
524  {
526  ::viRngUniform(method, ptr_, n, r, a, b), "MKLStream::uniform",
527  "::viRngUniform");
528  }
529 
531  int uniform_bits(MKL_INT n, unsigned *r,
532  MKL_INT method = VSL_RNG_METHOD_UNIFORMBITS_STD)
533  {
535  ::viRngUniformBits(method, ptr_, n, r), "MKLStream::uniform_bits",
536  "::viRngUniformBits");
537  }
538 
540  int uniform_bits32(MKL_INT n, unsigned *r,
541  MKL_INT method = VSL_RNG_METHOD_UNIFORMBITS32_STD)
542  {
544  ::viRngUniformBits32(method, ptr_, n, r),
545  "MKLStream::uniform_bits32", "::viRngUniformBits32");
546  }
547 
549  int uniform_bits64(MKL_INT n, unsigned MKL_INT64 *r,
550  MKL_INT method = VSL_RNG_METHOD_UNIFORMBITS64_STD)
551  {
553  ::viRngUniformBits64(method, ptr_, n, r),
554  "MKLStream::uniform_bits64", "::viRngUniformBits64");
555  }
556 
558  int bernoulli(MKL_INT n, int *r, double p,
559  MKL_INT method = VSL_RNG_METHOD_BERNOULLI_ICDF)
560  {
562  ::viRngBernoulli(method, ptr_, n, r, p), "MKLStream::bernoulli",
563  "::viRngBernoulli");
564  }
565 
567  int geometric(MKL_INT n, int *r, double p,
568  MKL_INT method = VSL_RNG_METHOD_GEOMETRIC_ICDF)
569  {
571  ::viRngGeometric(method, ptr_, n, r, p), "MKLStream::geometric",
572  "::viRngGeometric");
573  }
574 
576  int binomial(MKL_INT n, int *r, int ntrial, double p,
577  MKL_INT method = VSL_RNG_METHOD_BINOMIAL_BTPE)
578  {
580  ::viRngBinomial(method, ptr_, n, r, ntrial, p),
581  "MKLStream::binomial", "::viRngBinomial");
582  }
583 
585  int hypergeometric(MKL_INT n, int *r, int l, int s, int m,
586  MKL_INT method = VSL_RNG_METHOD_HYPERGEOMETRIC_H2PE)
587  {
589  ::viRngHypergeometric(method, ptr_, n, r, l, s, m),
590  "MKLStream::hypergeometric", "::viRngHypergeometric");
591  }
592 
594  int poisson(MKL_INT n, int *r, double lambda,
595  MKL_INT method = VSL_RNG_METHOD_POISSON_PTPE)
596  {
598  ::viRngPoisson(method, ptr_, n, r, lambda), "MKLStream::poisson",
599  "::viRngPoisson");
600  }
601 
603  int poisson_v(MKL_INT n, int *r, const double *lambda,
604  MKL_INT method = VSL_RNG_METHOD_POISSONV_POISNORM)
605  {
607  ::viRngPoissonV(method, ptr_, n, r, lambda),
608  "MKLStream::poisson_v", "::viRngPoissonV");
609  }
610 
612  int neg_binomial(MKL_INT n, int *r, double a, double p,
613  MKL_INT method = VSL_RNG_METHOD_NEGBINOMIAL_NBAR)
614  {
616  ::viRngNegbinomial(method, ptr_, n, r, a, p),
617  "MKLStream::neg_binomial", "::viRngNegbinomial");
618  }
619 
620  private:
621  ::VSLStreamStatePtr ptr_;
622 }; // class MKLStream
623 
626 inline bool operator==(const MKLStream &stream1, const MKLStream &stream2)
627 {
628  int brng1 = stream1.get_brng();
629  int brng2 = stream2.get_brng();
630  if (brng1 != brng2)
631  return false;
632  if (brng1 == VSL_BRNG_NONDETERM)
633  return false;
634 
635  std::size_t n = static_cast<std::size_t>(stream1.get_size());
636  Vector<char> s1(n);
637  Vector<char> s2(n);
638  stream1.save_m(s1.data());
639  stream2.save_m(s2.data());
640  if (s1 != s2)
641  return false;
642 
643  return true;
644 }
645 
648 inline bool operator!=(const MKLStream &stream1, const MKLStream &stream2)
649 {
650  return !(stream1 == stream2);
651 }
652 
655 template <typename CharT, typename Traits>
656 inline std::basic_ostream<CharT, Traits> &operator<<(
657  std::basic_ostream<CharT, Traits> &os, const MKLStream &stream)
658 {
659  if (!os)
660  return os;
661 
662  std::size_t n = static_cast<std::size_t>(stream.get_size());
663  std::size_t m = sizeof(std::uintmax_t);
664  if (n % m != 0)
665  n += m - n % m;
666  n /= m;
668  stream.save_m(reinterpret_cast<char *>(s.data()));
669 
670  os << stream.get_brng() << ' ';
671  os << s;
672 
673  return os;
674 }
675 
678 template <typename CharT, typename Traits>
679 inline std::basic_istream<CharT, Traits> &operator>>(
680  std::basic_istream<CharT, Traits> &is, MKLStream &stream)
681 {
682  if (!is)
683  return is;
684 
685  MKL_INT brng;
687  is >> std::ws >> brng;
688  is >> std::ws >> s;
689 
690  if (is) {
691  MKLStream tmp;
692  tmp.load_m(reinterpret_cast<const char *>(s.data()));
693  stream = std::move(tmp);
694  }
695 
696  return is;
697 }
698 
699 namespace internal
700 {
701 
702 template <MKL_INT BRNG>
703 class MKLMaxOffset : public std::integral_constant<MKL_INT, 0>
704 {
705 }; // MKLMaxOffset;
706 
707 template <>
708 class MKLMaxOffset<VSL_BRNG_MT2203>
709  : public std::integral_constant<MKL_INT, 6024>
710 {
711 }; // MKLMaxOffset
712 
713 template <>
714 class MKLMaxOffset<VSL_BRNG_WH> : public std::integral_constant<MKL_INT, 273>
715 {
716 }; // MKLMaxOffset
717 
718 template <MKL_INT BRNG, MKL_INT MaxOffset = MKLMaxOffset<BRNG>::value>
720 {
721  public:
722  static MKL_INT eval(MKL_INT offset)
723  {
725 
726  return BRNG + offset % MaxOffset;
727  }
728 }; // class MKLOffset
729 
730 template <MKL_INT BRNG>
731 class MKLOffset<BRNG, 0>
732 {
733  public:
734  static MKL_INT eval(MKL_INT) { return BRNG; }
735 }; // class MKLOffset
736 
737 template <int>
739 
740 template <>
742 {
743  public:
744  using type = unsigned;
745 }; // class MKLResultTypeTrait
746 
747 template <>
749 {
750  public:
751  using type = unsigned MKL_INT64;
752 }; // class MKLResultTypeTrait
753 
754 template <int Bits>
756 
757 template <int>
759 
760 template <>
761 class MKLUniformBits<32>
762 {
763  public:
764  static void eval(MKLStream &stream, MKL_INT n, unsigned *r)
765  {
766  stream.uniform_bits32(n, r);
767  }
768 }; // class MKLUniformBits
769 
770 template <>
771 class MKLUniformBits<64>
772 {
773  public:
774  static void eval(MKLStream &stream, MKL_INT n, unsigned MKL_INT64 *r)
775  {
776  stream.uniform_bits64(n, r);
777  }
778 }; // class MKLUniformBits
779 
780 } // namespace vsmc::internal
781 
790 template <MKL_INT BRNG, int Bits>
791 class MKLEngine
792 {
793  static_assert(Bits == 32 || Bits == 64,
794  "**MKLEngine** USED WITH Bits OTHER THAN 32, OR 64");
795 
796  public:
798 
799  explicit MKLEngine(result_type s = 1) : index_(M_) { seed(s); }
800 
801  template <typename SeedSeq>
802  explicit MKLEngine(SeedSeq &seq,
803  typename std::enable_if<internal::is_seed_seq<SeedSeq, MKL_INT,
804  result_type, MKLEngine<BRNG, Bits>>::value>::type * = nullptr)
805  : index_(M_)
806  {
807  seed(seq);
808  }
809 
810  MKLEngine(MKL_INT offset, result_type s) : index_(M_)
811  {
812  static_assert(internal::MKLMaxOffset<BRNG>::value > 0,
813  "**MKLEngine** DOES NOT SUPPORT OFFSETING");
814 
815  seed(offset, s);
816  }
817 
818  template <typename SeedSeq>
819  explicit MKLEngine(MKL_INT offset, SeedSeq &seq,
820  typename std::enable_if<internal::is_seed_seq<SeedSeq, MKL_INT,
821  MKL_UINT, MKLEngine<BRNG, Bits>>::value>::type * = nullptr)
822  : index_(M_)
823  {
824  static_assert(internal::MKLMaxOffset<BRNG>::value > 0,
825  "**MKLEngine** DOES NOT SUPPORT OFFSETING");
826 
827  seed(offset, seq);
828  }
829 
831  {
832  s %= static_cast<result_type>(std::numeric_limits<MKL_UINT>::max());
833  MKL_INT brng = stream_.empty() ? BRNG : stream_.get_brng();
834  stream_.reset(brng, static_cast<MKL_UINT>(s));
835  index_ = M_;
836  }
837 
838  template <typename SeedSeq>
839  void seed(
840  SeedSeq &seq, typename std::enable_if<internal::is_seed_seq<SeedSeq,
841  MKL_INT, result_type>::value>::type * = nullptr)
842  {
843  MKL_INT brng = stream_.empty() ? BRNG : stream_.get_brng();
844  Vector<MKL_UINT> params;
845  MKL_INT n = seed_params(brng, seq, params);
846  stream_.reset(brng, n, params.data());
847  index_ = M_;
848  }
849 
850  void seed(MKL_INT offset, result_type s)
851  {
852  static_assert(internal::MKLMaxOffset<BRNG>::value > 0,
853  "**MKLEngine** DOES NOT SUPPORT OFFSETING");
854 
855  s %= static_cast<result_type>(std::numeric_limits<MKL_UINT>::max());
856  MKL_INT brng = internal::MKLOffset<BRNG>::eval(offset);
857  stream_.reset(brng, static_cast<MKL_UINT>(s));
858  index_ = M_;
859  }
860 
861  template <typename SeedSeq>
862  void seed(MKL_INT offset, SeedSeq &seq,
863  typename std::enable_if<
865  {
866  static_assert(internal::MKLMaxOffset<BRNG>::value > 0,
867  "**MKLEngine** DOES NOT SUPPORT OFFSETING");
868 
869  MKL_INT brng = internal::MKLOffset<BRNG>::eval(offset);
870  Vector<unsigned> params;
871  MKL_INT n = seed_params(brng, seq, params);
872  stream_.reset(brng, n, params.data());
873  index_ = M_;
874  }
875 
877  {
878  if (index_ == M_) {
879  generate();
880  index_ = 0;
881  }
882 
883  return buffer_[index_++];
884  }
885 
886  void operator()(std::size_t n, result_type *r)
887  {
888  internal::size_check<MKL_INT>(n, "MKLEngine::operator()");
889 
890  const std::size_t remain = M_ - index_;
891 
892  if (n < remain) {
893  std::copy_n(buffer_.data() + index_, n, r);
894  index_ += n;
895  return;
896  }
897 
898  std::copy_n(buffer_.data() + index_, remain, r);
899  r += remain;
900  n -= remain;
901  index_ = M_;
902 
903  const std::size_t m = n / M_ * M_;
904  const std::size_t l = n % M_;
906  stream_, static_cast<MKL_INT>(m), r);
907  r += m;
908 
909  generate();
910  std::copy_n(buffer_.data(), l, r);
911  index_ = l;
912  }
913 
915  std::size_t discard()
916  {
917  const std::size_t remain = M_ - index_;
918  index_ = M_;
919 
920  return remain;
921  }
922 
923  void discard(long long nskip)
924  {
926 
927  if (nskip == 0)
928  return;
929 
930  const long long remain = static_cast<long long>(M_ - index_);
931  if (nskip <= remain) {
932  index_ += static_cast<std::size_t>(nskip);
933  return;
934  }
935  nskip -= remain;
936  index_ = M_;
937 
938  ::VSLBRngProperties properties;
939  MKLStream::get_brng_properties(stream_.get_brng(), &properties);
940  const int bits = properties.NBits;
941  const long long M = static_cast<long long>(M_);
942  long long m = nskip / M * M;
943  if (Bits >= bits)
944  m *= Bits / bits + (Bits % bits == 0 ? 0 : 1);
945  switch (stream_.get_brng()) {
946  case VSL_BRNG_MCG31: stream_.skip_ahead(m); break;
947  case VSL_BRNG_MRG32K3A: stream_.skip_ahead(m); break;
948  case VSL_BRNG_MCG59: stream_.skip_ahead(m); break;
949  case VSL_BRNG_WH: stream_.skip_ahead(m); break;
950  case VSL_BRNG_MT19937: stream_.skip_ahead(m); break;
951  case VSL_BRNG_SFMT19937: stream_.skip_ahead(m); break;
952  case VSL_BRNG_SOBOL: stream_.skip_ahead(m); break;
953  case VSL_BRNG_NIEDERR: stream_.skip_ahead(m); break;
954 #if INTEL_MKL_VERSION >= 110300
955  case VSL_BRNG_PHILOX4X32X10: stream_.skip_ahead(m); break;
956  case VSL_BRNG_ARS5: stream_.skip_ahead(m); break;
957 #endif
958  default:
959  while (nskip >= M) {
960  generate();
961  nskip -= M;
962  }
963  };
964  generate();
965  index_ = static_cast<std::size_t>(nskip % M);
966  }
967 
968  static constexpr result_type min()
969  {
970  return std::numeric_limits<result_type>::min();
971  }
972 
973  static constexpr result_type max()
974  {
975  return std::numeric_limits<result_type>::max();
976  }
977 
978  MKLStream &stream() { return stream_; }
979  const MKLStream &stream() const { return stream_; }
980 
984  friend bool operator==(
985  const MKLEngine<BRNG, Bits> &eng1, const MKLEngine<BRNG, Bits> &eng2)
986  {
987  if (eng1.stream_ != eng2.stream_)
988  return false;
989  if (eng1.buffer_ != eng2.buffer_)
990  return false;
991  if (eng1.index_ != eng2.index_)
992  return false;
993  return true;
994  }
995 
999  friend bool operator!=(
1000  const MKLEngine<BRNG, Bits> &eng1, const MKLEngine<BRNG, Bits> &eng2)
1001  {
1002  return !(eng1 == eng2);
1003  }
1004 
1005  template <typename CharT, typename Traits>
1006  friend std::basic_ostream<CharT, Traits> &operator<<(
1007  std::basic_ostream<CharT, Traits> &os,
1008  const MKLEngine<BRNG, Bits> &eng)
1009  {
1010  if (!os)
1011  return os;
1012 
1013  os << eng.stream_ << ' ';
1014  os << eng.buffer_ << ' ';
1015  os << eng.index_;
1016 
1017  return os;
1018  }
1019 
1020  template <typename CharT, typename Traits>
1021  friend std::basic_istream<CharT, Traits> &operator>>(
1022  std::basic_istream<CharT, Traits> &is, MKLEngine<BRNG, Bits> &eng)
1023  {
1024  if (!is)
1025  return is;
1026 
1027  MKLStream stream;
1028  Vector<result_type> buffer;
1029  std::size_t index;
1030  is >> std::ws >> stream;
1031  is >> std::ws >> buffer;
1032  is >> std::ws >> index;
1033 
1034  if (is) {
1035  eng.stream_ = std::move(stream);
1036  eng.buffer_ = std::move(buffer);
1037  eng.index_ = index;
1038  }
1039 
1040  return is;
1041  }
1042 
1043  private:
1044  static constexpr std::size_t M_ = internal::BufferSize<result_type>::value;
1045 
1046  Vector<result_type> buffer_;
1047  std::size_t index_;
1048  MKLStream stream_;
1049 
1050  void generate()
1051  {
1052  buffer_.resize(M_);
1054  stream_, static_cast<MKL_INT>(M_), buffer_.data());
1055  }
1056 
1057  template <typename SeedSeq>
1058  MKL_INT seed_params(MKL_INT brng, SeedSeq &seq, Vector<unsigned> &params)
1059  {
1060  ::VSLBRngProperties properties;
1061  MKLStream::get_brng_properties(brng, &properties);
1062  MKL_INT n = properties.NSeeds;
1063  params.resize(static_cast<std::size_t>(n));
1064  seq.generate(params.begin(), params.end());
1065 
1066  return n;
1067  }
1068 }; // class MKLEngine
1069 
1073 
1077 
1081 
1085 
1089 
1093 
1098 
1103 
1107 
1111 
1112 #if INTEL_MKL_VERSION >= 110300
1113 
1116 using MKL_ARS5 = MKLEngine<VSL_BRNG_ARS5, 32>;
1117 
1120 using MKL_ARS5_64 = MKLEngine<VSL_BRNG_ARS5, 64>;
1121 
1124 using MKL_PHILOX4X32X10 = MKLEngine<VSL_BRNG_PHILOX4X32X10, 32>;
1125 
1128 using MKL_PHILOX4X32X10_64 = MKLEngine<VSL_BRNG_PHILOX4X32X10, 64>;
1129 
1130 #endif // INTEL_MKL_VERSION >= 110300
1131 
1132 template <MKL_INT BRNG, int Bits>
1133 inline void rand(MKLEngine<BRNG, Bits> &rng, std::size_t n,
1135 {
1136  rng(n, r);
1137 }
1138 
1139 template <MKL_INT BRNG, int Bits>
1140 inline void beta_distribution(MKLEngine<BRNG, Bits> &rng, std::size_t n,
1141  float *r, float alpha, float beta)
1142 {
1143  internal::size_check<MKL_INT>(n, "beta_distribution)");
1144  rng.stream().beta(static_cast<MKL_INT>(n), r, alpha, beta, 0, 1);
1145 }
1146 
1147 template <MKL_INT BRNG, int Bits>
1148 inline void beta_distribution(MKLEngine<BRNG, Bits> &rng, std::size_t n,
1149  double *r, double alpha, double beta)
1150 {
1151  internal::size_check<MKL_INT>(n, "beta_distribution)");
1152  rng.stream().beta(static_cast<MKL_INT>(n), r, alpha, beta, 0, 1);
1153 }
1154 
1155 template <MKL_INT BRNG, int Bits>
1157  MKLEngine<BRNG, Bits> &rng, std::size_t n, float *r, float a, float b)
1158 {
1159  internal::size_check<MKL_INT>(n, "cauchy_distribution)");
1160  rng.stream().cauchy(static_cast<MKL_INT>(n), r, a, b);
1161 }
1162 
1163 template <MKL_INT BRNG, int Bits>
1165  MKLEngine<BRNG, Bits> &rng, std::size_t n, double *r, double a, double b)
1166 {
1167  internal::size_check<MKL_INT>(n, "cauchy_distribution)");
1168  rng.stream().cauchy(static_cast<MKL_INT>(n), r, a, b);
1169 }
1170 
1171 template <MKL_INT BRNG, int Bits>
1173  MKLEngine<BRNG, Bits> &rng, std::size_t n, float *r, float lambda)
1174 {
1175  internal::size_check<MKL_INT>(n, "exponential_distribution)");
1176  rng.stream().exponential(static_cast<MKL_INT>(n), r, 0, 1 / lambda);
1177 }
1178 
1179 template <MKL_INT BRNG, int Bits>
1181  MKLEngine<BRNG, Bits> &rng, std::size_t n, double *r, double lambda)
1182 {
1183  internal::size_check<MKL_INT>(n, "exponential_distribution)");
1184  rng.stream().exponential(static_cast<MKL_INT>(n), r, 0, 1 / lambda);
1185 }
1186 
1187 template <MKL_INT BRNG, int Bits>
1189  MKLEngine<BRNG, Bits> &rng, std::size_t n, float *r, float a, float b)
1190 {
1191  internal::size_check<MKL_INT>(n, "extreme_value_distribution)");
1192  rng.stream().gumbel(static_cast<MKL_INT>(n), r, a, b);
1193  sub(n, 2 * a, r, r);
1194 }
1195 
1196 template <MKL_INT BRNG, int Bits>
1198  MKLEngine<BRNG, Bits> &rng, std::size_t n, double *r, double a, double b)
1199 {
1200  internal::size_check<MKL_INT>(n, "extreme_value_distribution)");
1201  rng.stream().gumbel(static_cast<MKL_INT>(n), r, a, b);
1202  sub(n, 2 * a, r, r);
1203 }
1204 
1205 template <MKL_INT BRNG, int Bits>
1206 inline void gamma_distribution(MKLEngine<BRNG, Bits> &rng, std::size_t n,
1207  float *r, float alpha, float beta)
1208 {
1209  internal::size_check<MKL_INT>(n, "gamma_distribution)");
1210  rng.stream().gamma(static_cast<MKL_INT>(n), r, alpha, 0, beta);
1211 }
1212 
1213 template <MKL_INT BRNG, int Bits>
1214 inline void gamma_distribution(MKLEngine<BRNG, Bits> &rng, std::size_t n,
1215  double *r, double alpha, double beta)
1216 {
1217  internal::size_check<MKL_INT>(n, "gamma_distribution)");
1218  rng.stream().gamma(static_cast<MKL_INT>(n), r, alpha, 0, beta);
1219 }
1220 
1221 template <MKL_INT BRNG, int Bits>
1222 inline void laplace_distribution(MKLEngine<BRNG, Bits> &rng, std::size_t n,
1223  float *r, float location, float scale)
1224 {
1225  internal::size_check<MKL_INT>(n, "lapace_distribution)");
1226  rng.stream().laplace(static_cast<MKL_INT>(n), r, location, scale);
1227 }
1228 
1229 template <MKL_INT BRNG, int Bits>
1230 inline void laplace_distribution(MKLEngine<BRNG, Bits> &rng, std::size_t n,
1231  double *r, double location, double scale)
1232 {
1233  internal::size_check<MKL_INT>(n, "lapace_distribution)");
1234  rng.stream().laplace(static_cast<MKL_INT>(n), r, location, scale);
1235 }
1236 
1237 template <MKL_INT BRNG, int Bits>
1239  MKLEngine<BRNG, Bits> &rng, std::size_t n, float *r, float m, float s)
1240 {
1241  internal::size_check<MKL_INT>(n, "lognormal_distribution)");
1242  rng.stream().lognormal(static_cast<MKL_INT>(n), r, m, s, 0, 1);
1243 }
1244 
1245 template <MKL_INT BRNG, int Bits>
1247  MKLEngine<BRNG, Bits> &rng, std::size_t n, double *r, double m, double s)
1248 {
1249  internal::size_check<MKL_INT>(n, "lognormal_distribution)");
1250  rng.stream().lognormal(static_cast<MKL_INT>(n), r, m, s, 0, 1);
1251 }
1252 
1253 template <MKL_INT BRNG, int Bits>
1254 inline void normal_distribution(MKLEngine<BRNG, Bits> &rng, std::size_t n,
1255  float *r, float mean, float stddev)
1256 {
1257  internal::size_check<MKL_INT>(n, "normal_distribution)");
1258  rng.stream().gaussian(static_cast<MKL_INT>(n), r, mean, stddev);
1259 }
1260 
1261 template <MKL_INT BRNG, int Bits>
1262 inline void normal_distribution(MKLEngine<BRNG, Bits> &rng, std::size_t n,
1263  double *r, double mean, double stddev)
1264 {
1265  internal::size_check<MKL_INT>(n, "normal_distribution)");
1266  rng.stream().gaussian(static_cast<MKL_INT>(n), r, mean, stddev);
1267 }
1268 
1269 template <MKL_INT BRNG, int Bits>
1270 inline void normal_mv_distribution(MKLEngine<BRNG, Bits> &rng, std::size_t n,
1271  float *r, std::size_t m, const float *mean, const float *chol)
1272 {
1273  internal::size_check<MKL_INT>(n, "normal_mv_distribution)");
1274  internal::size_check<MKL_INT>(m, "normal_mv_distribution)");
1275  rng.stream().gaussian_mv(static_cast<MKL_INT>(n), r,
1276  static_cast<MKL_INT>(m), VSL_MATRIX_STORAGE_PACKED, mean, chol);
1277 }
1278 
1279 template <MKL_INT BRNG, int Bits>
1280 inline void normal_mv_distribution(MKLEngine<BRNG, Bits> &rng, std::size_t n,
1281  double *r, std::size_t m, const double *mean, const double *chol)
1282 {
1283  internal::size_check<MKL_INT>(n, "normal_mv_distribution)");
1284  internal::size_check<MKL_INT>(m, "normal_mv_distribution)");
1285  rng.stream().gaussian_mv(static_cast<MKL_INT>(n), r,
1286  static_cast<MKL_INT>(m), VSL_MATRIX_STORAGE_PACKED, mean, chol);
1287 }
1288 
1289 template <MKL_INT BRNG, int Bits>
1291  MKLEngine<BRNG, Bits> &rng, std::size_t n, float *r, float sigma)
1292 {
1293  internal::size_check<MKL_INT>(n, "rayleigh_distribution)");
1294  rng.stream().rayleigh(
1295  static_cast<MKL_INT>(n), r, 0, const_sqrt_2<float>() * sigma);
1296 }
1297 
1298 template <MKL_INT BRNG, int Bits>
1300  MKLEngine<BRNG, Bits> &rng, std::size_t n, double *r, double sigma)
1301 {
1302  internal::size_check<MKL_INT>(n, "rayleigh_distribution)");
1303  rng.stream().rayleigh(
1304  static_cast<MKL_INT>(n), r, 0, const_sqrt_2<double>() * sigma);
1305 }
1306 
1307 template <MKL_INT BRNG, int Bits>
1308 inline void u01_distribution(
1309  MKLEngine<BRNG, Bits> &rng, std::size_t n, float *r)
1310 {
1311  internal::size_check<MKL_INT>(n, "u01_distribution)");
1312  rng.stream().uniform(static_cast<MKL_INT>(n), r, 0, 1);
1313 }
1314 
1315 template <MKL_INT BRNG, int Bits>
1316 inline void u01_distribution(
1317  MKLEngine<BRNG, Bits> &rng, std::size_t n, double *r)
1318 {
1319  internal::size_check<MKL_INT>(n, "u01_distribution)");
1320  rng.stream().uniform(static_cast<MKL_INT>(n), r, 0, 1);
1321 }
1322 
1323 template <MKL_INT BRNG, int Bits>
1325  MKLEngine<BRNG, Bits> &rng, std::size_t n, float *r)
1326 {
1327  internal::size_check<MKL_INT>(n, "u01_co_distribution)");
1328  rng.stream().uniform(static_cast<MKL_INT>(n), r, 0, 1);
1329 }
1330 
1331 template <MKL_INT BRNG, int Bits>
1333  MKLEngine<BRNG, Bits> &rng, std::size_t n, double *r)
1334 {
1335  internal::size_check<MKL_INT>(n, "u01_co_distribution)");
1336  rng.stream().uniform(static_cast<MKL_INT>(n), r, 0, 1);
1337 }
1338 
1339 template <MKL_INT BRNG, int Bits>
1341  MKLEngine<BRNG, Bits> &rng, std::size_t n, float *r, float a, float b)
1342 {
1343  internal::size_check<MKL_INT>(n, "uniform_real_distribution)");
1344  rng.stream().uniform(static_cast<MKL_INT>(n), r, a, b);
1345 }
1346 
1347 template <MKL_INT BRNG, int Bits>
1349  MKLEngine<BRNG, Bits> &rng, std::size_t n, double *r, double a, double b)
1350 {
1351  internal::size_check<MKL_INT>(n, "uniform_real_distribution)");
1352  rng.stream().uniform(static_cast<MKL_INT>(n), r, a, b);
1353 }
1354 
1355 template <MKL_INT BRNG, int Bits>
1357  MKLEngine<BRNG, Bits> &rng, std::size_t n, float *r, float a, float b)
1358 {
1359  internal::size_check<MKL_INT>(n, "weibull_distribution)");
1360  rng.stream().weibull(static_cast<MKL_INT>(n), r, a, 0, b);
1361 }
1362 
1363 template <MKL_INT BRNG, int Bits>
1365  MKLEngine<BRNG, Bits> &rng, std::size_t n, double *r, double a, double b)
1366 {
1367  internal::size_check<MKL_INT>(n, "weibull_distribution)");
1368  rng.stream().weibull(static_cast<MKL_INT>(n), r, a, 0, b);
1369 }
1370 
1371 namespace internal
1372 {
1373 
1374 template <typename RNGType>
1376 {
1377  public:
1378  unsigned reserved1[2];
1379  unsigned reserved2[2];
1380  RNGType rng;
1381 }; // class MKLStreamState
1382 
1383 template <typename RNGType>
1384 inline constexpr int mkl_nseeds(std::false_type)
1385 {
1386  return (sizeof(typename RNGType::ctr_type) +
1387  sizeof(typename RNGType::key_type)) /
1388  sizeof(unsigned);
1389 }
1390 
1391 template <typename RNGType>
1392 inline constexpr int mkl_nseeds(std::true_type)
1393 {
1394  return 1;
1395 }
1396 
1397 template <typename RNGType>
1398 inline constexpr int mkl_nseeds()
1399 {
1400  return mkl_nseeds<RNGType>(std::integral_constant<
1401  bool, (std::is_same<CtrType<RNGType>, NullType>::value ||
1402  std::is_same<KeyType<RNGType>, NullType>::value)>());
1403 }
1404 
1405 template <typename RNGType>
1406 inline int mkl_init(
1407  RNGType &rng, int n, const unsigned *param, std::false_type)
1408 {
1409  int nc = static_cast<int>(
1410  sizeof(typename RNGType::ctr_type) / sizeof(unsigned));
1411  int nk = static_cast<int>(
1412  sizeof(typename RNGType::key_type) / sizeof(unsigned));
1413  new (static_cast<void *>(&rng)) RNGType();
1414 
1415  if (n > 0) {
1416  std::size_t size =
1417  static_cast<std::size_t>(std::min(n, nk)) * sizeof(unsigned);
1418  typename RNGType::key_type key;
1419  std::fill(key.begin(), key.end(), 0);
1420  std::memcpy(key.data(), param, size);
1421  rng.key(key);
1422  }
1423 
1424  if (n > nk) {
1425  n -= nk;
1426  param += nk;
1427  std::size_t size =
1428  static_cast<std::size_t>(std::min(n, nc)) * sizeof(unsigned);
1429  typename RNGType::ctr_type ctr;
1430  std::fill(ctr.begin(), ctr.end(), 0);
1431  std::memcpy(ctr.data(), param, size);
1432  rng.ctr(ctr);
1433  }
1434 
1435  return 0;
1436 }
1437 
1438 template <typename RNGType>
1439 inline int mkl_init(RNGType &rng, int n, const unsigned *param, std::true_type)
1440 {
1441  if (n == 0) {
1442  new (static_cast<void *>(&rng)) RNGType();
1443  } else {
1444  new (static_cast<void *>(&rng))
1445  RNGType(static_cast<typename RNGType::result_type>(param[0]));
1446  }
1447 
1448  return 0;
1449 }
1450 
1451 template <typename RNGType>
1452 inline int mkl_init(
1453  int method, ::VSLStreamStatePtr stream, int n, const unsigned *param)
1454 {
1455  RNGType &rng = (*reinterpret_cast<MKLStreamState<RNGType> *>(stream)).rng;
1456 
1457  if (method == VSL_INIT_METHOD_STANDARD) {
1458  return mkl_init(
1459  rng, n, param,
1460  std::integral_constant<
1461  bool, (std::is_same<CtrType<RNGType>, NullType>::value ||
1462  std::is_same<KeyType<RNGType>, NullType>::value)>());
1463  }
1464 
1465  if (method == VSL_INIT_METHOD_LEAPFROG)
1466  return VSL_RNG_ERROR_LEAPFROG_UNSUPPORTED;
1467 
1468  if (method == VSL_INIT_METHOD_SKIPAHEAD)
1469  rng.discard(static_cast<unsigned>(n));
1470 
1471  return 0;
1472 }
1473 
1474 template <typename RNGType, typename RealType>
1475 inline int mkl_uniform_real(
1476  ::VSLStreamStatePtr stream, int n, RealType *r, RealType a, RealType b)
1477 {
1478  RNGType &rng = (*reinterpret_cast<MKLStreamState<RNGType> *>(stream)).rng;
1479  uniform_real_distribution(rng, static_cast<std::size_t>(n), r, a, b);
1480 
1481  return 0;
1482 }
1483 
1484 template <typename RNGType>
1485 inline int mkl_uniform_int(::VSLStreamStatePtr stream, int n, unsigned *r)
1486 {
1487  RNGType &rng = (*reinterpret_cast<MKLStreamState<RNGType> *>(stream)).rng;
1488  uniform_bits_distribution(rng, static_cast<std::size_t>(n), r);
1489 
1490  return 0;
1491 }
1492 
1493 } // namespace vsmc::internal
1494 
1501 template <typename RNGType>
1502 inline int mkl_brng()
1503 {
1504  static ::VSLBRngProperties properties = {
1506  internal::mkl_nseeds<RNGType>(), 1, 4, 32, internal::mkl_init<RNGType>,
1507  internal::mkl_uniform_real<RNGType, float>,
1508  internal::mkl_uniform_real<RNGType, double>,
1509  internal::mkl_uniform_int<RNGType>};
1510  static int brng = ::vslRegisterBrng(&properties);
1511 
1512  return brng;
1513 }
1514 
1515 } // namespace vsmc
1516 
1517 #endif // VSMC_RNG_MKL_HPP
std::vector< T, Alloc > Vector
std::vector with Allocator as default allocator
int gumbel(MKL_INT n, float *r, float a, float beta, MKL_INT method=VSL_RNG_METHOD_GUMBEL_ICDF)
vsRngGumbel
Definition: mkl.hpp:468
MKLStream & operator=(MKLStream &&other)
Definition: mkl.hpp:130
bool empty() const
Definition: mkl.hpp:191
void cauchy_distribution(RNGType &rng, std::size_t N, RealType *r, RealType a, RealType b)
Generating Cauchy random variates.
Definition: monitor.hpp:48
static int get_num_reg_brngs()
vslGetNumRegBrngs
Definition: mkl.hpp:254
static MKL_INT eval(MKL_INT)
Definition: mkl.hpp:734
std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, std::array< T, N > &ary)
Definition: basic.hpp:303
MKLStream(MKL_INT brng, MKL_INT n, unsigned *params)
vslNewStreamEx
Definition: mkl.hpp:98
int gamma(MKL_INT n, double *r, double alpha, double a, double beta, MKL_INT method=VSL_RNG_METHOD_GAMMA_GNORM)
vdRngGamma
Definition: mkl.hpp:495
int exponential(MKL_INT n, float *r, float a, float beta, MKL_INT method=VSL_RNG_METHOD_EXPONENTIAL_ICDF)
vsRngExponential
Definition: mkl.hpp:360
int uniform_bits32(MKL_INT n, unsigned *r, MKL_INT method=VSL_RNG_METHOD_UNIFORMBITS32_STD)
viRngUniform32
Definition: mkl.hpp:540
int gaussian_mv(MKL_INT n, float *r, MKL_INT dimen, MKL_INT mstorage, const float *a, const float *t, MKL_INT method=VSL_RNG_METHOD_GAUSSIANMV_BOXMULLER2)
vsRngGaussianMV
Definition: mkl.hpp:340
std::size_t discard()
Discard the buffer.
Definition: mkl.hpp:915
result_type operator()()
Definition: mkl.hpp:876
#define VSMC_RUNTIME_WARNING_RNG_MKL_OFFSET
Definition: mkl.hpp:38
int geometric(MKL_INT n, int *r, double p, MKL_INT method=VSL_RNG_METHOD_GEOMETRIC_ICDF)
viRngGeometric
Definition: mkl.hpp:567
int gaussian(MKL_INT n, double *r, double a, double sigma, MKL_INT method=VSL_RNG_METHOD_GAUSSIAN_BOXMULLER2)
vdRngGaussian
Definition: mkl.hpp:331
void normal_mv_distribution(RNGType &, std::size_t, RealType *, std::size_t, const RealType *, const RealType *)
Generating multivariate Normal random varaites.
int gaussian(MKL_INT n, float *r, float a, float sigma, MKL_INT method=VSL_RNG_METHOD_GAUSSIAN_BOXMULLER2)
vsRngGaussian
Definition: mkl.hpp:322
constexpr double const_sqrt_2< double >() noexcept
Definition: constants.hpp:215
int rayleigh(MKL_INT n, double *r, double a, double beta, MKL_INT method=VSL_RNG_METHOD_RAYLEIGH_ICDF)
vdRngRayleigh
Definition: mkl.hpp:441
static bool has_leap_frog(MKL_INT brng)
Test if vslLeapfrogStream is supported.
Definition: mkl.hpp:266
int release()
vslDeleteStream
Definition: mkl.hpp:179
int leapfrog(MKL_INT k, MKL_INT nstreams)
vslLeapfrogStream
Definition: mkl.hpp:236
int get_size() const
vslGetStreamSize
Definition: mkl.hpp:233
int neg_binomial(MKL_INT n, int *r, double a, double p, MKL_INT method=VSL_RNG_METHOD_NEGBINOMIAL_NBAR)
viRngNegbinomial
Definition: mkl.hpp:612
MKLStream(MKL_INT brng, MKL_UINT seed)
vslNewStream
Definition: mkl.hpp:92
#define VSMC_RUNTIME_ASSERT(cond, msg)
Definition: assert.hpp:59
typename CtrTypeTrait< T >::type CtrType
int gumbel(MKL_INT n, double *r, double a, double beta, MKL_INT method=VSL_RNG_METHOD_GUMBEL_ICDF)
vdRngGumbel
Definition: mkl.hpp:477
int get_brng() const
vslGetStreamStateBrng
Definition: mkl.hpp:251
void seed(SeedSeq &seq, typename std::enable_if< internal::is_seed_seq< SeedSeq, MKL_INT, result_type >::value >::type *=nullptr)
Definition: mkl.hpp:839
int hypergeometric(MKL_INT n, int *r, int l, int s, int m, MKL_INT method=VSL_RNG_METHOD_HYPERGEOMETRIC_H2PE)
viRngHypergeometric
Definition: mkl.hpp:585
static int get_brng_properties(MKL_INT brng,::VSLBRngProperties *properties)
vslGetBrngProperties
Definition: mkl.hpp:257
void seed(MKL_INT offset, result_type s)
Definition: mkl.hpp:850
constexpr int mkl_nseeds(std::false_type)
Definition: mkl.hpp:1384
friend bool operator==(const MKLEngine< BRNG, Bits > &eng1, const MKLEngine< BRNG, Bits > &eng2)
eng1 == eng2 is a sufficent condition for subsequent call of operator() output the same results...
Definition: mkl.hpp:984
static bool has_uniform_bits32(MKL_INT brng, MKL_INT method=VSL_RNG_METHOD_UNIFORMBITS32_STD)
Test if viRngUniformBits32 is supported.
Definition: mkl.hpp:282
MKL RNG C++11 engine.
MKLStream(MKLStream &&other)
Definition: mkl.hpp:128
int uniform(MKL_INT n, float *r, float a, float b, MKL_INT method=VSL_RNG_METHOD_UNIFORM_STD)
vsRngUniform
Definition: mkl.hpp:304
int poisson_v(MKL_INT n, int *r, const double *lambda, MKL_INT method=VSL_RNG_METHOD_POISSONV_POISNORM)
viRngPoissonV
Definition: mkl.hpp:603
void rayleigh_distribution(RNGType &, std::size_t, RealType *, RealType)
Generating rayleigh random variates.
static bool has_skip_ahead(MKL_INT brng)
Test if vslSkipAheadStream is supported.
Definition: mkl.hpp:274
bool operator!=(const SingleParticle< T > &sp1, const SingleParticle< T > &sp2)
int poisson(MKL_INT n, int *r, double lambda, MKL_INT method=VSL_RNG_METHOD_POISSON_PTPE)
viRngPoisson
Definition: mkl.hpp:594
void u01_distribution(RNGType &, std::size_t, RealType *)
Generate standard uniform random variates.
void extreme_value_distribution(RNGType &rng, std::size_t N, RealType *r, RealType a, RealType b)
Generating extreme value random variates.
int uniform(MKL_INT n, double *r, double a, double b, MKL_INT method=VSL_RNG_METHOD_UNIFORM_STD)
vdRngUniform
Definition: mkl.hpp:313
static MKL_INT eval(MKL_INT offset)
Definition: mkl.hpp:722
int reset(::VSLStreamStatePtr ptr)
Definition: mkl.hpp:144
MKLStream(::VSLStreamStatePtr ptr=nullptr)
Definition: mkl.hpp:86
int uniform(MKL_INT n, int *r, int a, int b, MKL_INT method=VSL_RNG_METHOD_UNIFORM_STD)
viRngUniform
Definition: mkl.hpp:522
int reset(MKL_INT brng, MKL_INT n, unsigned *params)
vslNewStreamEx
Definition: mkl.hpp:166
void discard(long long nskip)
Definition: mkl.hpp:923
void normal_distribution(RNGType &, std::size_t, RealType *, RealType, RealType)
Generating Normal random variates.
int save_m(char *memptr) const
vslSaveStreamM
Definition: mkl.hpp:214
static constexpr result_type min()
Definition: mkl.hpp:968
int beta(MKL_INT n, float *r, float p, float q, float a, float beta, MKL_INT method=VSL_RNG_METHOD_BETA_CJA)
vsRngBeta
Definition: mkl.hpp:504
typename KeyTypeTrait< T >::type KeyType
int beta(MKL_INT n, double *r, double p, double q, double a, double beta, MKL_INT method=VSL_RNG_METHOD_BETA_CJA)
vdRngBeta
Definition: mkl.hpp:513
static void eval(MKLStream &stream, MKL_INT n, unsigned MKL_INT64 *r)
Definition: mkl.hpp:774
int reset(MKL_INT brng, MKL_UINT seed)
vslNewStream
Definition: mkl.hpp:153
MKLEngine(MKL_INT offset, SeedSeq &seq, typename std::enable_if< internal::is_seed_seq< SeedSeq, MKL_INT, MKL_UINT, MKLEngine< BRNG, Bits >>::value >::type *=nullptr)
Definition: mkl.hpp:819
const MKLStream & stream() const
Definition: mkl.hpp:979
int weibull(MKL_INT n, double *r, double alpha, double a, double beta, MKL_INT method=VSL_RNG_METHOD_WEIBULL_ICDF)
vdRngWeibull
Definition: mkl.hpp:405
int gaussian_mv(MKL_INT n, double *r, MKL_INT dimen, MKL_INT mstorage, const double *a, const double *t, MKL_INT method=VSL_RNG_METHOD_GAUSSIANMV_BOXMULLER2)
vdRngGaussianMV
Definition: mkl.hpp:350
bool operator==(const SingleParticle< T > &sp1, const SingleParticle< T > &sp2)
int lognormal(MKL_INT n, float *r, float a, float sigma, float b, float beta, MKL_INT method=VSL_RNG_METHOD_LOGNORMAL_BOXMULLER2)
vsRngLognormal
Definition: mkl.hpp:450
int skip_ahead(long long nskip)
vslSkipAheadStream
Definition: mkl.hpp:244
int load_f(const std::string &fname)
vslSaveStreamF
Definition: mkl.hpp:201
std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const std::array< T, N > &ary)
Definition: basic.hpp:296
int weibull(MKL_INT n, float *r, float alpha, float a, float beta, MKL_INT method=VSL_RNG_METHOD_WEIBULL_ICDF)
vsRngWeibull
Definition: mkl.hpp:396
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, MKLEngine< BRNG, Bits > &eng)
Definition: mkl.hpp:1021
static bool has_uniform_bits64(MKL_INT brng, MKL_INT method=VSL_RNG_METHOD_UNIFORMBITS64_STD)
Test if viRngUniformBits64 is supported.
Definition: mkl.hpp:293
int load_m(const char *memptr)
vslLoadStreamM
Definition: mkl.hpp:221
int uniform_bits64(MKL_INT n, unsigned MKL_INT64 *r, MKL_INT method=VSL_RNG_METHOD_UNIFORMBITS64_STD)
viRngUniform64
Definition: mkl.hpp:549
int mkl_uniform_int(::VSLStreamStatePtr stream, int n, unsigned *r)
Definition: mkl.hpp:1485
int bernoulli(MKL_INT n, int *r, double p, MKL_INT method=VSL_RNG_METHOD_BERNOULLI_ICDF)
viRngBernoulli
Definition: mkl.hpp:558
constexpr float const_sqrt_2< float >() noexcept
Definition: constants.hpp:215
int cauchy(MKL_INT n, double *r, double a, double beta, MKL_INT method=VSL_RNG_METHOD_CAUCHY_ICDF)
vdRngCauchy
Definition: mkl.hpp:423
friend bool operator!=(const MKLEngine< BRNG, Bits > &eng1, const MKLEngine< BRNG, Bits > &eng2)
eng1 != eng2 is a necessary condition for subsequent call of operator() output different results...
Definition: mkl.hpp:999
int mkl_uniform_real(::VSLStreamStatePtr stream, int n, RealType *r, RealType a, RealType b)
Definition: mkl.hpp:1475
int lognormal(MKL_INT n, double *r, double a, double sigma, double b, double beta, MKL_INT method=VSL_RNG_METHOD_LOGNORMAL_BOXMULLER2)
vdRngLognormal
Definition: mkl.hpp:459
void sub(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:75
MKLEngine(MKL_INT offset, result_type s)
Definition: mkl.hpp:810
int mkl_error_check(int status, const char *cpp, const char *c)
Definition: mkl.hpp:58
MKLEngine(SeedSeq &seq, typename std::enable_if< internal::is_seed_seq< SeedSeq, MKL_INT, result_type, MKLEngine< BRNG, Bits >>::value >::type *=nullptr)
Definition: mkl.hpp:802
int rayleigh(MKL_INT n, float *r, float a, float beta, MKL_INT method=VSL_RNG_METHOD_RAYLEIGH_ICDF)
vsRngRayleigh
Definition: mkl.hpp:432
void lognormal_distribution(RNGType &, std::size_t, RealType *, RealType, RealType)
Generating lognormal random variates.
MKLEngine(result_type s=1)
Definition: mkl.hpp:799
void seed(MKL_INT offset, SeedSeq &seq, typename std::enable_if< internal::is_seed_seq< SeedSeq, MKL_UINT >::value >::type *=nullptr)
Definition: mkl.hpp:862
void rand(RNGType &rng, ArcsineDistribution< RealType > &dist, std::size_t N, RealType *r)
void laplace_distribution(RNGType &, std::size_t, RealType *, RealType, RealType)
Generating laplace random variates.
MKL VSLStreamStatePtr wrapper.
Definition: mkl.hpp:83
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const MKLEngine< BRNG, Bits > &eng)
Definition: mkl.hpp:1006
MKLStream & stream()
Definition: mkl.hpp:978
int save_f(const std::string &fname) const
vslSaveStreamF
Definition: mkl.hpp:194
void uniform_real_distribution(RNGType &, std::size_t, RealType *, RealType, RealType)
Generate uniform real random variates with open/closed variants.
void beta_distribution(RNGType &rng, std::size_t n, RealType *r, RealType alpha, RealType beta)
Generating Beta random variates.
void weibull_distribution(RNGType &, std::size_t, RealType *, RealType, RealType)
Generating weibull random variates.
static constexpr result_type max()
Definition: mkl.hpp:973
void exponential_distribution(RNGType &rng, std::size_t N, RealType *r, RealType lambda)
Generating exponential random variates.
void uniform_bits_distribution(RNGType &, std::size_t, UIntType *)
int gamma(MKL_INT n, float *r, float alpha, float a, float beta, MKL_INT method=VSL_RNG_METHOD_GAMMA_GNORM)
vsRngGamma
Definition: mkl.hpp:486
int mkl_brng()
Register a C++11 RNG as MKL BRNG.
Definition: mkl.hpp:1502
static void eval(MKLStream &stream, MKL_INT n, unsigned *r)
Definition: mkl.hpp:764
int laplace(MKL_INT n, float *r, float a, float beta, MKL_INT method=VSL_RNG_METHOD_LAPLACE_ICDF)
vsRngLaplace
Definition: mkl.hpp:378
~MKLStream()
vslDeleteStream
Definition: mkl.hpp:142
MKLStream(const MKLStream &other)
vslCopyStream
Definition: mkl.hpp:104
void operator()(std::size_t n, result_type *r)
Definition: mkl.hpp:886
int uniform_bits(MKL_INT n, unsigned *r, MKL_INT method=VSL_RNG_METHOD_UNIFORMBITS_STD)
viRngUniform
Definition: mkl.hpp:531
int binomial(MKL_INT n, int *r, int ntrial, double p, MKL_INT method=VSL_RNG_METHOD_BINOMIAL_BTPE)
viRngBinomial
Definition: mkl.hpp:576
int mkl_init(RNGType &rng, int n, const unsigned *param, std::false_type)
Definition: mkl.hpp:1406
int exponential(MKL_INT n, double *r, double a, double beta, MKL_INT method=VSL_RNG_METHOD_EXPONENTIAL_ICDF)
vdRngExponential
Definition: mkl.hpp:369
void gamma_distribution(RNGType &rng, std::size_t n, RealType *r, RealType alpha, RealType beta)
Generating gamma random variates.
MKLStream & operator=(const MKLStream &other)
vslCopyStream/vslCopySreamState
Definition: mkl.hpp:114
int laplace(MKL_INT n, double *r, double a, double beta, MKL_INT method=VSL_RNG_METHOD_LAPLACE_ICDF)
vdRngLaplace
Definition: mkl.hpp:387
internal::MKLResultType< Bits > result_type
Definition: mkl.hpp:797
void seed(result_type s)
Definition: mkl.hpp:830
typename MKLResultTypeTrait< Bits >::type MKLResultType
Definition: mkl.hpp:755
void u01_co_distribution(MKLEngine< BRNG, Bits > &rng, std::size_t n, float *r)
Definition: mkl.hpp:1324
#define VSMC_RUNTIME_ASSERT_RNG_MKL_DISCARD
Definition: mkl.hpp:42
int cauchy(MKL_INT n, float *r, float a, float beta, MKL_INT method=VSL_RNG_METHOD_CAUCHY_ICDF)
vsRngCauchy
Definition: mkl.hpp:414