vSMC  v3.0.0
Scalable Monte Carlo
rdrand.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/rng/rdrand.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_RDRAND_HPP
33 #define VSMC_RNG_RDRAND_HPP
34 
36 #include <immintrin.h>
37 
38 #ifndef VSMC_RNG_RDRAND_NTRIAL_MAX
39 #define VSMC_RNG_RDRAND_NTRIAL_MAX 0
40 #endif
41 
42 #define VSMC_RUNTIME_WARNING_RNG_RDRAND_ENGINE_NTRIAL(ntrial, NTrialMax) \
43  VSMC_RUNTIME_WARNING((ntrial < NTrialMax), \
44  "**RDRAND::generate** MAXIMUM NUMBER OF TRIALS EXCEEDED")
45 
46 namespace vsmc
47 {
48 
51 template <typename UIntType, std::size_t W>
52 inline bool rdrand(UIntType *, std::integral_constant<int, W>);
53 
56 template <typename UIntType>
57 inline bool rdrand(UIntType *rand, std::integral_constant<int, 16>)
58 {
59  unsigned short r;
60  int cf = _rdrand16_step(&r);
61  *rand = static_cast<UIntType>(r);
62 
63  return cf != 0;
64 }
65 
68 template <typename UIntType>
69 inline bool rdrand(UIntType *rand, std::integral_constant<int, 32>)
70 {
71  unsigned r;
72  int cf = _rdrand32_step(&r);
73  *rand = static_cast<UIntType>(r);
74 
75  return cf != 0;
76 }
77 
80 template <typename UIntType>
81 inline bool rdrand(UIntType *rand, std::integral_constant<int, 64>)
82 {
83 #if defined(VSMC_MSVC) || (defined(VSMC_INTEL) && VSMC_INTEL_VERSION < 1600)
84  unsigned __int64 r;
85 #else
86  unsigned long long r;
87 #endif
88  int cf = _rdrand64_step(&r);
89  *rand = static_cast<UIntType>(r);
90 
91  return cf != 0;
92 }
93 
96 template <typename ResultType,
97  std::size_t NTrialMax = VSMC_RNG_RDRAND_NTRIAL_MAX>
99 {
100  static_assert(std::is_unsigned<ResultType>::value,
101  "**RDRANDEngine** USED WITH ResultType OTHER THAN UNSIGNED INTEGER "
102  "TYPES");
103 
104  static_assert(std::numeric_limits<ResultType>::digits == 16 ||
105  std::numeric_limits<ResultType>::digits == 32 ||
106  std::numeric_limits<ResultType>::digits == 64,
107  "**RDRANDEngine** USED WITH ResultType OF SIZE OTHER THAN 16, 32 OR "
108  "64 BITS");
109 
110  public:
111  using result_type = ResultType;
112 
113  explicit RDRANDEngine(result_type = 0) {}
114 
115  template <typename SeedSeq>
116  explicit RDRANDEngine(SeedSeq &,
117  typename std::enable_if<internal::is_seed_seq<SeedSeq, result_type,
118  RDRANDEngine<ResultType, NTrialMax>>::value>::type * = nullptr)
119  {
120  }
121 
122  void seed(result_type) {}
123 
124  template <typename SeedSeq>
125  void seed(SeedSeq &, typename std::enable_if<internal::is_seed_seq<SeedSeq,
126  result_type>::value>::type * = nullptr)
127  {
128  }
129 
131  {
132  return generate(std::integral_constant<bool, NTrialMax != 0>());
133  }
134 
135  void discard(std::size_t) {}
136 
137  static constexpr result_type min()
138  {
139  return std::numeric_limits<result_type>::min();
140  }
141 
142  static constexpr result_type max()
143  {
144  return std::numeric_limits<result_type>::max();
145  }
146 
149  {
150  return false;
151  }
152 
155  {
156  return true;
157  }
158 
159  template <typename CharT, typename CharTraits>
160  friend std::basic_ostream<CharT, CharTraits> &operator<<(
161  std::basic_ostream<CharT, CharTraits> &os,
163  {
164  return os;
165  }
166 
167  template <typename CharT, typename CharTraits>
168  friend std::basic_istream<CharT, CharTraits> &operator>>(
169  std::basic_istream<CharT, CharTraits> &is,
171  {
172  return is;
173  }
174 
175  private:
176  result_type generate(std::true_type)
177  {
178  result_type r;
179  std::size_t ntrial = 0;
180  while (true) {
181  ++ntrial;
182  bool success = rdrand<result_type>(
183  &r, std::integral_constant<int,
184  std::numeric_limits<result_type>::digits>());
185  if (success || ntrial > NTrialMax)
186  break;
187  }
189 
190  return r;
191  }
192 
193  result_type generate(std::false_type)
194  {
195  result_type r;
196  while (true) {
197  bool success = rdrand<result_type>(
198  &r, std::integral_constant<int,
199  std::numeric_limits<result_type>::digits>());
200  if (success)
201  break;
202  }
203 
204  return r;
205  }
206 }; // class RDRANDEngine
207 
211 
215 
219 
220 } // namespace vsmc
221 
222 #endif // VSMC_RNG_RDRAND_HPP
RDRAND generator.
Definition: rdrand.hpp:98
friend bool operator==(const RDRANDEngine< ResultType, NTrialMax > &, const RDRANDEngine< ResultType, NTrialMax > &)
Definition: rdrand.hpp:147
Definition: monitor.hpp:48
static constexpr result_type max()
Definition: rdrand.hpp:142
ResultType result_type
Definition: rdrand.hpp:111
friend bool operator!=(const RDRANDEngine< ResultType, NTrialMax > &, const RDRANDEngine< ResultType, NTrialMax > &)
Definition: rdrand.hpp:153
result_type operator()()
Definition: rdrand.hpp:130
static constexpr result_type min()
Definition: rdrand.hpp:137
void seed(SeedSeq &, typename std::enable_if< internal::is_seed_seq< SeedSeq, result_type >::value >::type *=nullptr)
Definition: rdrand.hpp:125
RDRANDEngine(SeedSeq &, typename std::enable_if< internal::is_seed_seq< SeedSeq, result_type, RDRANDEngine< ResultType, NTrialMax >>::value >::type *=nullptr)
Definition: rdrand.hpp:116
friend std::basic_ostream< CharT, CharTraits > & operator<<(std::basic_ostream< CharT, CharTraits > &os, const RDRANDEngine< ResultType, NTrialMax > &)
Definition: rdrand.hpp:160
void discard(std::size_t)
Definition: rdrand.hpp:135
#define VSMC_RNG_RDRAND_NTRIAL_MAX
Definition: rdrand.hpp:39
RDRANDEngine(result_type=0)
Definition: rdrand.hpp:113
void seed(result_type)
Definition: rdrand.hpp:122
friend std::basic_istream< CharT, CharTraits > & operator>>(std::basic_istream< CharT, CharTraits > &is, RDRANDEngine< ResultType, NTrialMax > &)
Definition: rdrand.hpp:168
bool rdrand(UIntType *, std::integral_constant< int, W >)
Invoke the RDRAND instruction and return the carry flag.
void rand(RNGType &rng, ArcsineDistribution< RealType > &dist, std::size_t N, RealType *r)
#define VSMC_RUNTIME_WARNING_RNG_RDRAND_ENGINE_NTRIAL(ntrial, NTrialMax)
Definition: rdrand.hpp:42